0

This is the first time I develop an Java application and immediately face an issue. Now I have a SQL query as below:

Select PD.* From product PD
join Stock SP on PD.id = SP.product_id
join storage SR on SR.id = SP.storage_id
join status ST on ST.storage_id = SR.id
where ST.id ='1qa7n234i'

My entities:

public class Product extends MainEntity {
   public Product(){}
   public void setAtcKey(String pAtcKey) {
    atcKey = pAtcKey;
   }
}

public class StockPosition extends MainEntity {
   public StockPosition(){}
   @XmlIDREF
    public Product getProduct() {
        return product;
    }

    public void setProduct(Product pProduct) {
        product = pProduct;
    }

    @XmlIDREF
    public Storage getStorage() {
        return storage;
    }

    public void setStorage(Storage pStorage) {
        storage = pStorage;
    }
}

public class Storage extends MainEntity {
   public Storage(){}
   @XmlTransient
   public Station getStation() {
    return station;
   }

   public void setStation(Station pStation) {
    station = pStation;
   }
}

public class Status extends MainEntity {
   public Status(){}
}

So I convert it to CriteriaQuery like:

CriteriaBuilder cb = getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root<Product> product = query.from(Product.class);
Join<StockPosition, Product> sp = product.join(StockPosition_.product);

But I got an error message likeThe method join(SingularAttribute<? super Product,Y>) in the type From<Product,Product> is not applicable for the arguments (SingularAttribute<StockPosition,Product>)? This message is very strange for me (because I am newbie). Thank you

Phong Vo
  • 1,078
  • 7
  • 16
  • did you mean HQL query? – sanbhat Apr 24 '13 at 11:35
  • I am using: `javax.persistence.criteria.Join` – Phong Vo Apr 24 '13 at 11:37
  • Would you explain more and give us more details – Khalil Apr 24 '13 at 11:42
  • 1
    This means that you are trying to build a criteria query. This is not the only way, you can also write queries with [jpql](http://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html) that is easier for starters. Anyway if you want a criteria query, use the corresponding tag and be aware that _there are_ valuable answers here on SO. If you still need help, post the entities and what you have already done – perissf Apr 24 '13 at 11:43
  • I just update my question, thank you, mates. – Phong Vo Apr 24 '13 at 11:51
  • You have to reverse the join: `Join sp = product.join(Product_.stockPositionCollection)` do you have a property like `stockPositionCollection` in `Product` ? – perissf Apr 24 '13 at 11:59
  • Actually, I have three entities, Product, StockPosition and Status. StockPosition holds Product_id fk and status_id fk, other entities do not hold stockposition_id but I want to get all records from product entity. Thank you for your quick response @perissf – Phong Vo Apr 24 '13 at 12:08
  • Please edit your question by adding the entities and the relevant relationship properties – perissf Apr 24 '13 at 12:24
  • I just updated my question – Phong Vo Apr 24 '13 at 12:47

3 Answers3

1
CriteriaBuilder cb = getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root<Product> product = query.from(Product.class);
Join<StockPosition, Product> sp = product.join(StockPosition_.product);

I think it should look like this:

CriteriaBuilder cb = getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root<Product> product = query.from(Product.class);
Join<StockPosition, Product> sp = product.join(Product_.stockposition);

Maybe you think to much in a way of SQL joins.

If you don't need to build the query at runtime you may consider to use JPQL instead.

JPQL with NamedQueries: http://www.objectdb.com/java/jpa/query/named

Maybe this help you on other questions about JPA http://www.objectdb.com/java/jpa/query/criteria

Do you build the metamodel classes on your own? Or did you use an "Meta Model Generator" provided by your persistence framework?

Hope this helps.

André
  • 167
  • 2
  • 8
0

Your join is not correct. If your Root is in the Product (Root<Product>) then you must join using an attribute present in the Product class.

In this case, your Productclass should define an attribute like:

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
private List<StockPosition> stackPositions;

And then perform the join as follows:

Join<Product, StackPosition> sp = product.join(Product_.stackPositions_);
Predicate p = cb.equal(sp.get(StackPosition_.id, "1qa7n234i");
...
Marc Nuri
  • 2,729
  • 1
  • 14
  • 18
-1

If you have one-to-one relationship in your DB model, then having a class and Annotation like below should give you the result.

Basically, you will fetch the Stock, and get stock.storage.status (which is joined as per the @javax.peristence.JoinColumn clause)

class Product {

@OnetoOne
@JoinColumn(name="product_id")
Stock stock;

}

class Stock {

@OnetoOne
@JoinColumn(name="storage_id")
Storage storage;

}

class Storage {

@OnetoOne
@JoinColumn(name="storage_id")
Status status;

}
sanbhat
  • 17,522
  • 6
  • 48
  • 64