Page 1 of 1

About Question enthuware.oce-jpad.v6.2.580 :

Posted: Sat Sep 15, 2012 11:41 am
by jszczepankiewicz
The following line will result in compilation exception (incompatible types):

TypedQuery tq = em.createQuery(cq); //6

so the line should be changed to be compilable.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Sun Sep 16, 2012 6:53 am
by admin
jszczepankiewicz wrote:The following line will result in compilation exception (incompatible types):

TypedQuery tq = em.createQuery(cq); //6

so the line should be changed to be compilable.
That is not true because return type of this method is TypeQuery as per the JavaDoc API description:

<T> TypedQuery<T>
createQuery(CriteriaQuery<T> criteriaQuery)
Create an instance of TypedQuery for executing a criteria query.
Is there any other reason that I missed?

-Paul.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Mon Sep 17, 2012 12:43 am
by jszczepankiewicz
Hi,

em.createQuery(String name) returns Query NOT supertype TypedQuery, this lines of code is not compilable. To fix this you should change:
em.createQuery(String name, X.class) -> this will return TypedQuery (generic) and will not result in compilation error.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Mon Sep 17, 2012 12:46 am
by jszczepankiewicz
Sorry, you are right, and I'm the one who made a mistake, sorry for the confusion ;)

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 4:11 am
by cliviu
Hi, I tried to create 2 customers each with 3 orders and to run the original query as it is, it returns always two results instead of six, as expected

In the explanation is stated that "Therefore, when you add two roots Customer and CustOrder and there is not where condition to limit the result set, it will return cartesian product of the two tables i.e. 3x2=6 rows. Further, since the code is selecting Customer ( cq.select(custRoot);), it will return 6 Customer objects. 4 of them will be duplicates."


What am I doing wrong or understand wrong ?

Thanks,
Liviu

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 6:48 am
by admin
Can you please post the exact code that you are running? Because that doesn't seem right.

-Paul.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 7:09 am
by cliviu

Code: Select all

@Entity
public class SimpleCustomer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public SimpleCustomer(){
    }
                
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof SimpleCustomer)) {
            return false;
        }
        SimpleCustomer other = (SimpleCustomer) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }
    
    public void addSimpleCustOrder(SimpleCustOrder custOrder)
    {        
        custOrder.setCustomer(this);
    }

    @Override
    public String toString() {
        return "simplejpa.SimpleCustomer[ id=" + id + " ]";
    }

}

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 7:10 am
by cliviu

Code: Select all

@Entity
public class SimpleCustOrder implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @ManyToOne
    private SimpleCustomer customer;

    public SimpleCustomer getCustomer() {
        return customer;
    }

    public void setCustomer(SimpleCustomer customer) {
        this.customer = customer;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof SimpleCustOrder)) {
            return false;
        }
        SimpleCustOrder other = (SimpleCustOrder) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "simplejpa.SimpleCustOrder[ id=" + id + " ]";
    }

}

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 7:10 am
by cliviu

Code: Select all


public class SimpleJpa1 {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        EntityManagerFactory emf =  Persistence.createEntityManagerFactory("projpa2");
        EntityManager em  = emf.createEntityManager();
        
        EntityTransaction tx = em.getTransaction();
        
        tx.begin();                
        SimpleCustomer person = new SimpleCustomer();        
        person.setName("Customer1");
        SimpleCustomer person1 = new SimpleCustomer();        
        person1.setName("Customer2");
        
        SimpleCustOrder order1 =  new SimpleCustOrder();
        SimpleCustOrder order2 =  new SimpleCustOrder();
        SimpleCustOrder order3 =  new SimpleCustOrder();
        SimpleCustOrder order4 =  new SimpleCustOrder();
        SimpleCustOrder order5 =  new SimpleCustOrder();
        SimpleCustOrder order6 =  new SimpleCustOrder();
        person.addSimpleCustOrder(order1);
        person.addSimpleCustOrder(order2);
        person.addSimpleCustOrder(order3);
        
        person1.addSimpleCustOrder(order4);
        person1.addSimpleCustOrder(order5);        
        person1.addSimpleCustOrder(order6);        
        
        em.persist(person1);
        em.persist(person);
        em.persist(order1);                
        em.persist(order2);
        em.persist(order3);
        em.persist(order4);
        em.persist(order5);
        em.persist(order6);
        tx.commit();
        
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery cq1 = cb.createQuery();
        Root custRoot = cq1.from(SimpleCustomer.class);        
        Root orderRoot = cq1.from(SimpleCustOrder.class);        
        cq1.select(custRoot);
        TypedQuery tq1 = em.createQuery(cq1);
        List result1 = (List) tq1.getResultList();
        System.out.println("Result size " + result1.size());                       
    }    
}


Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 9:29 am
by admin
What JPA provider are you using? I mean, Hibernate or EclipseLink or something else?
The JavaDoc API description is clear on how CriteriaQuery.from works. It says,
Create and add a query root corresponding to the given entity, forming a cartesian product with any existing roots.
HTH,
Paul.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 9:50 am
by cliviu
Hi Paul,

I use EclipseLink. You mean that is something wrong with the implementation ?

Thanks,
Liviu

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Oct 18, 2013 10:18 am
by admin
cliviu wrote:Hi Paul,

I use EclipseLink. You mean that is something wrong with the implementation ?

Thanks,
Liviu
That is certainly a possibility. We have seen several cases where implementation does not exactly comply with the specification. Let me confirm with the author on which implementation and version this was tested because there can differences because of versions as well.

I see that the explanation contains the query that gets generated, which aligns well with the API description. So I suspect that what you see is probably because of non compliant behavior.

HTH,
Paul.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Mon Oct 21, 2013 4:20 am
by cliviu
Hi Paul,
With JBoss I have 12 results , sounds right 2X6 ... with Eclipse Link only 2.

Nevertheless , in the explanation is given 2X3 results, which is correct only when the two users share the same three orders.
Please correct me if I'm wrong ...

Thanks,
Liviu

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Mon Oct 21, 2013 10:01 am
by admin
Yes, you are right. It should be 12.
Paul.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Wed Feb 04, 2015 6:25 am
by swiss-chris
I'm a bit confused by the following explanation:

"2. In this case, you cannot join Customer with CustOrder (though the reverse is possible) because Customer does not have a Collection of CustOrders. (It is given in the problem statement that CustOrder to Customer is a unidirectional many to one relationship.)"

My SQL skills are probably a bit outdated, but in pure SQL, isn't it possible to join in either direction even on a unidirectional relationship?

In other words, can't I do

SELECT DISTINCT *
FROM Customer c
INNER JOIN CustOrder;

when only CustOrder has FK references to Customer?

Over at http://www.w3schools.com/sql/trysql.asp ... select_all I just tried:

SELECT DISTINCT *
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID;

This worked fine, even though Orders is the owning side (FK from Orders pointing to PK of Customers)

If this is possible in MySQL, why does CriteryQuery [edit: replaced JPQL with CriteriaQuery, as this is what the exam question is about] care in which direction you specify the FROM and JOIN?

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Wed Feb 04, 2015 9:05 am
by admin
Yes, it is certainly possible with pure sql but not with JPQL. JQPL traverses the object graph and builds sql querries off of that. So if there is no variable from A to B in A, it can't traverse from A to B.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Wed Feb 04, 2015 12:22 pm
by swiss-chris
admin wrote:Yes, it is certainly possible with pure sql but not with JPQL. JQPL traverses the object graph and builds sql querries off of that. So if there is no variable from A to B in A, it can't traverse from A to B.
Thanks for your reply!
I just realized that I meant CriteriaQuery, not JPQL. How does it work with CriteriaQuery? Where can I find this behavior documented in the specification?

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Wed Feb 04, 2015 9:08 pm
by admin
Same thing with CriterialQuery as well. You can go through the specification for more details.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Fri Sep 04, 2015 2:56 am
by romsky
I think the explanation for 4th option has to go to the first one.

Re: About Question enthuware.oce-jpad.v6.2.580 :

Posted: Sun Sep 06, 2015 1:27 am
by admin
It looks ok. Explanation to option 4 gives 2 reasons why it is incorrect. Option 1 is correct anyway.