Eclipselink: Create objects from JOIN query - java

I have a SQL query
SELECT * FROM Thing AS a JOIN Thing_Property AS b ON a.id=b.Thing_ID
JOIN Property AS c ON b.properties_ID = c.id
JOIN Item AS d ON c.item_ID = d.id
ORDER BY a.name, d.name
and I Eclipselink to create my object model with it.
Here is the model:
#SuppressWarnings("serial")
#Entity
public class Thing implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
private String name;
#OneToMany(cascade=CascadeType.ALL)
#PrivateOwned
private List<Property> properties = new ArrayList<Property>();
...
// getter and setter following here
}
public class Property implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
#OneToOne
private Item item;
private String value;
...
// getter and setter following here
}
public class Item implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
private String name;
....
// getter and setter following here
}
// Code end
but I can not figure out, how to make Eclipselink create the model from that query. Can you help?

You will need to use the API EntityManager.createNativeQuery(String sqlString, Class resultClass);
entityManager.createNativeQuery("SELECT * FROM Thing AS a JOIN Thing_Property AS b ON a.id=b.Thing_ID JOIN Property AS c ON b.properties_ID = c.id JOIN Item AS d ON c.item_ID = d.id ORDER BY a.name, d.name ", Thing.class);

Related

Hibernate query to Sql query

My entity of product looks like below:
#Entity
#Table(name = "order")
public class OrderEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "order_id")
private Long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "order_products",
joinColumns = #JoinColumn(name = "order_id", referencedColumnName = "order_id"),
inverseJoinColumns = #JoinColumn(name = "product_id", referencedColumnName = "id")
)
private Set<ProductEntity> products = new HashSet<>();
}
ProductEntity:
#Entity
#Table(name = "product")
public class ProductEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true)
private String name;
#ManyToMany(mappedBy = "products")
private Set<OrderEntity> orders = new HashSet<>();
}
I want to get all orders where product name is equal to wanted value. And I write sql query to get result from database, but I cannot write hibernate query for Spring Data JPA.
My query for postgreSQL looks like this:
SELECT o.order_id, op.product_id, p.name
FROM public.order o
INNER JOIN public.order_products op
ON p.order_id = op.product_id
INNER JOIN public.product p
ON op.product_id = p.id
WHERE p.name = 'Foo';
And this query return me an id of order, product_id and name of product. And this works. But I didn't know how to write this question as spring query using #Query.
I need a metohod in my repository:
#Repository
public interface OrderRepository extends JpaRepository<OrderEntity, Long> {
#Query("") <- place for my query in Hibernate sql
List<OrderEntity> findAllByProductName(#Param("name") String name);
}
try this: (it returns full OrderEntity objects )
#Query("select o from OrderEntity o join o.products prod where prod.name = :name")
List<OrderEntity> findAllByProductName(#Param("name") String name);
if you need fetch eager all data for products use : ....OrderEntity o join o.products... in query instead of OrderEntity o join o.products
This is a projection consisting of columns from many entties, so you would have to go for the Result Class strategy.
Basically, you create a POJO class with expected result fields an an equivalent constructor:
public class ResultClass{
private Integer orderId;
private Integer productId;
private String name;
public ResultClass(Integer orderId, Integer productId, String name){
// set the fields
}
}
Then you alter the query a bit:
SELECT new com.mypkg.ResultClass(o.order_id, op.product_id, p.name)
FROM public.order o
INNER JOIN public.order_products op
ON p.order_id = op.product_id
INNER JOIN public.product p
ON op.product_id = p.id
WHERE p.name = 'Foo';
And change the return type on the interface method:
#Repository
public interface OrderRepository extends JpaRepository<OrderEntity, Long> {
#Query("...")
List<ResultClass> findAllByProductName(#Param("name") String name);
}

JPA Error: Path expected for join

In my java spring mvc application, i have two classes:
#Entity
public class Transactions {
#Id
#GeneratedValue
long id;
#OneToOne
Customer customer;
#OneToOne
Merchant merchant;
double value;
}
and the customer class is:
#Entity
public class Customer {
#Id
#GeneratedValue
long id;
String name;
String ageClass;
String language;
String cardUserArea;
}
The repository for the Transactions is:
#Repository
public interface TransactionRepository extends JpaRepository<Transactions ,Long >{
#Query("SELECT sum( value) FROM Transactions inner join Customer on Transactions.customer_id=Customer.id where merchant_id= ?1 and age_class= ?2 ")
public double getOverAllValue(String merchantID,String ageGroup);
}
But it complains with:
org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [SELECT sum( value) FROM ee.seb.domain.Transactions inner join Customer on Transactions.customer_id=Customer.id where merchant_id= ?1 and age_class= ?2 ]
The query runns successfully against the database
The answer was in using nativeQuery
#Query(value = "SELECT sum( value) FROM Transactions inner join Customer on Transactions.customer_id=Customer.id where merchant_id= ?1 and age_class= ?2 ", nativeQuery=true)
public double getOverAllValue(String merchantID,String ageGroup);
Below code is ex. of entity and relationship with other entity :-
#Entity
#Table(name = "F_AREA")
#NamedQuery(name = "FArea.findAll", query = "SELECT f FROM FArea f")
public class FArea implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "F_AREA_AREAID_GENERATOR", sequenceName = "SEQ_F_AREA")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "F_AREA_AREAID_GENERATOR")
#Column(name = "AREA_ID")
private long areaId;
#Column(name = "AREA_NAME_EN")
private String areaNameEn;
#Column(name = "AREA_STATUS")
private BigDecimal areaStatus;
#Column(name = "AREA_UPDATED_DATE")
private Timestamp areaUpdatedDate;
// bi-directional many-to-one association to FCity
#ManyToOne
#JoinColumn(name = "CITY_ID")
private FCity FCity;
// bi-directional many-to-one association to FCustomer
#OneToMany(mappedBy = "FArea")
private List<FCustomer> FCustomers;
.
.
.
.
}
Please update your query with this:
#Query("select sum(t.value) from Transactions t inner join t.customer c where c.id= ?1 and c.ageClass= ?2 ")
public Double getOverAllValue(long merchantID,String ageGroup);

JPQL to select entity based on grandchild attribute

I am trying to select an entity A that has a B that contains a list of C where the value C.d must match a parameter.
My entities look like this:
#Entity
class A {
#GeneratedValue
#Id
private Long id;
#Column(name="B")
#OneToOne(cascade=CascadeType.ALL)
#MapsId
private B b1;
}
#Entity
class B {
#GeneratedValue
#Id
private Long id;
#OneToMany(mappedBy="b2", cascade=CascadeType.ALL)
private List<C> cs;
}
#Entity
class C {
#GeneratedValue
#Id
private Long id;
#ManyToOne
#JoinColumn(name="B")
private B b2;
private String d;
}
My naive approach on selecting my entity look like this:
SELECT entity FROM A entity WHERE entity.b1.cs.d = :d
How should the query be structured?
Should be:
SELECT entity FROM A entity INNER JOIN entity.b1.cs CSList WHERE CSList.d = :d
Read about INNER JOIN in JPA.
http://www.thejavageek.com/2014/03/24/jpa-inner-joins/
try this
TypedQuery<A> query = em.createQuery("select b.a from B b inner join C c where c.d = :d",A.class);
List<A> a = query.getResultList();

Mapping / Join with #Transient entity field HQL

I have these entities:
#Entity
#Table(name = "my_table")
public class MyTable implements Serializable {
#Id
#Column(name = "RECORD_ID")
private Long recordId;
#Column(name = "CNAME")
private String changeName;
#Transient
MyTableTwo tableTwo;
//getters and setters
}
MyTableTwo entity:
#Entity
#Table(name = "my_table_two")
public class MyTableTwo implements Serializable {
#Id
#Column(name = "REC_ID")
private Long recId;
#Column(name = "CNAME")
private String changeName;
#Column(name = "CVAL")
private String changeValue;
//getters and setters
}
I want to get my_table.record_id. 'my_table.cname', 'my_table_two.cval' in a result.
How to write a query on these two entities?
Can we write a join query with first entity and #transient entity field of 2nd entity?
I need to write HQL
You can do a cross join like
select a,b from MyTable a,MyTableTwo b where a.prop1 = b.prop2

How do I join two tables in hibernate and Spring

How do I join two tables in hibernate and Spring. below is my suto java code and I need to do a join on objectA where the name field is equal to the name field in objectB but I am going to be searching on ObjectA ID field but I need returned. ObjectA ID, ObjectA Name, ObjectA Regin, ObjectB Address.
//
// CLASS OBJECT A
//
#Entity
#Table(name = "tableA")
public class ObjectA {
#Id
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "region")
private String region;
}
//
// CLASS OBJECT B
//
#Entity
#Table(name = "tableB")
public class ObjectB {
#Id
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "address")
private String address;
}
can someone please tell me how to do this within the java code.
Add this to your A class:
#OneToOne
#JoinColumn(name="name")
private ObjectB objectB;
So that when you retrieve for A, you'll get inside corresponding B by name.
Use a cross join with a condition in the where clause to limit the join. This is the only good way (other than native sql) that i know of, to join two objects when there is no mapped relationship between them.
You can do this easily with an hql query
select a.id, a.name, a.region, b. address
from ObjectA a, ObjectB b
where a.id = b.id
You can also use inner join
select A.ID,A.Name,A.Regin,B.Address
from ObjectA as A inner join ObjectB as B

Categories

Resources