Finding an inherited entity over a jointable with NamedQuery - jpa

How can I use a NamedQuery to find an entity over a jointable?
I have an abstract parent class/entity with #Inheritance(strategy=InheritanceType.JOINED) and two subclasses/subentities.
Hence, in the database I have a parent table (sdrs) and two subtables (xSdrs and ySdrs).
There is another table reservations which shall have a Many-to-Many relationship to table sdrs. That's why I created a jointable between reservations and sdrs.
I intend to have a NamedQuery in the parent entity Sdr to be able to find the key for a record/entity of XSdr or YSdr respectively over the jointable.
In class Sdr I have:
#NamedQuery(name="Sdr.findBySdrId", query="SELECT s FROM Sdr s "
+ "INNER JOIN s.reservations res WHERE res.sdrs = :transactionId")
and
#ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
#JoinTable(name="sdrs_has_reservations",
joinColumns = {
#JoinColumn(name="sdrs_id", referencedColumnName="sdrId", nullable=false)
}, inverseJoinColumns={
#JoinColumn(name="reservations_id", referencedColumnName="reservationId", nullable=false)
})
private List<Reservation<T>> reservations;
But, of course, this sets the transactionId to reservationId which consequentially fails.
On the inverse side I have:
#ManyToMany(mappedBy="reservations", fetch=FetchType.EAGER)
private List<Sdr<T>> sdrs;
So, how do I have to implement the named query in class/entity Sdr to be able to get the proper Sdr (and its related reservations) with an Sdr ID to be set as query parameter?

SELECT sdr FROM Reservation r JOIN r.sdrs sdr WHERE sdr.id=:id

Related

JPA Query Left Join with A non-declared relation

I need to query an Entity with a left join with another entity. But I can only declare the ManyToOne relation on the left table:
First table:
#Entity
public class ShipyardModel {
private Long id
....etc
}
Second table (LEFT one):
#Entity
public class Boat{
private Long id;
...
#ManyToOne
#JoinColumn(name = "shipyard_model_id")
private ShipyardModel shipyardModel;
}
Because of serialization reasons I can't declare the #OneToMany relation in the first entity. But they are related, because in the Boat table, i have the shipyard_mode_id. So I created a DTO to query this guy for me and created a JPA query:
Query(" SELECT new br.com.easymarine.dto.ShipyardModelDTO" +
"(sm.id, sm.name, sm.commercialLength, sm.length, sm.width, sm.height, sm.beam, sm.weightWithoutMotor, sm.weightWithMotor, sm.modelYear, sm.shipType,s.id, s.name,count(b.id)) " +
"from ShipyardModel sm " +
"join sm.shipyard s " +
"left join Boat b on b.shipyardModel = sm GROUP BY sm.id")
List<ShipyardModelDTO> findAllShipyardModelDTO();
The Spring is giving me
Path expected for join!
error
Is it possible to execute this query the way it is?

Spring Data+JPA: enforce inner join for OneToOne relationship

I have an Entity with OneToOne relation, which is used just to sort results:
#Entity
public class Document {
#Id
Long id;
#OneToOne()
SortProperty sortProp;
...
}
Then I have repository (using QueryDSL predicates):
public interface DocumentRepository
implements PagingAndSortingRepository<Document, Long>,
QueryDslPredicateExecutor<Document> {
#EntityGraph(value = "Document.forceJoins")
Page<Document> findAll(Predicate queryDslPredicate, Pageable pageable);
...
}
As you see above, I use #EntityGraph to control joining relations in the main query. All this work well, the only problem is performance - #OneToOne is fetched vith left outer join which means that DB index is not used:
select * from
document document0_
left outer join
sortproperty sortproper3_
on document0_.documentid=sortproper3_.documentid
...
Is there any way how to enforce using inner join instead of left outer join?
I have tried several things - #OneToOne(optional = false), #org.hibernate.annotations.Fetch, but no success ... Parts generated from QueryDSL predicate(s) use properly inner joins for the property, but the main part of query use always left outer join. I was trying also use annotation with this method:
#Query("select doc from Document doc inner join doc.sortProperties props")
but I was unable to use it properly together with paging and QueryDSL predicates.
Any idea?
Try this with #Query annotation.
#Query("select doc from Document doc join doc.sortProp props")

Spring data JPA JPQL query on child property

I am using spring-data jpa. When querying parent object with child object property,I was expecting parent with aggregated child objects.I have OneToMany relation between User and Phone. Just typing some part of code.
#Query(select u from User u inner join u.phone ph where ph.active=:active)
Page<User> getAllUsers(#Param("active") int active);
#Entity
User{
#OneToMany(fetch=FetchType.LAZY)
List<Phone> phone;
}
#Entity
Phone{
#ManyToOne
User user;
}
My query returns multiple User object based on active phone quantity. I was expecting one User object and all aggregated phone object in the list as part of User object. Is my assumption is wrong or am I doing something wrong?
Try:
#Query(select distinct u from User u inner join u.phone ph where ph.active=:active)
Page<User> getAllUsers(#Param("active") int active);

Get an object list from an HQL query with joint

I have two tables: Customers and Commands, it's a #OneToMany relation from Client to Commands, one client have many Commands.
the table commands contain : idCommand, date, nameCommande, idCustomer.
the table customers contain: idCustomer, nameClient, email.
All the JPA and EJB are set up and I can easily get a list of Commands or Clients using an HQL query in a managed bean and list them in a JSP using this code.
public List<Commande> selectAllCommandes() {
List<Commande> commandes = em.createQuery("select c from Commande c").getResultList();
return commandes;
}
public List<Customer> selectAllCustomers() {
List<Customer> customers = em.createQuery("select cu from Customer cu").getResultList();
return customers;
}
How do I join the two tables with the idCustomer column in a way to show the name of client instead his id? I've used this HQL query
SELECT c.date, c.name Commande, cu.nameClient FROM Commande AS c, Customer AS cu WHERE cu.idCustomer = c.idCustomer
But I have no idea about the List<> type that I need to use to get the result/
If you map the reverse relation in the Commande entity ...
public class Commande {
...
#ManyToOne(mappedBy="commande")
private Client client;
// getter and setter ...
}
(Here, mappedBy is getting the name of the #OneToMany property set up at the
other side of the relationship)
Then after executing your query SELECT c FROM Commande c you would get a list of Commande objects, and for each one of them you could get the name of the client using: thisCommande.getClient().getName().

JPA OneToMany relations and performace

I have two entities: parent Customer and child Order.
Each Customer has 1,000,000 Orders for example, so it is not needed in any given time to load a Customer with all Orders but I want to have this ability to make join query on these two entities in JPA.
So because of this, I must create #OneToMany relationship for making join queries.
My question is: how to get query without making joinColumn because even in Lazy mode it is possible to load 1,000,000 objects!
I just want to get query on these object with where restrictions like native join.
If you don't want the #OneToMany relationship implicitly set in your Customer class than you don't have to. You can execute JPQL queries (in very precise manner) without the marked relationship.
Assume you have:
#Entity
public class Customer {
// all Customer-related fields WITHOUT #OneToMany relationship with Order
}
#Entity
public class Order {
#ManyToOne
private Customer owner;
}
Then if you want to get all Orders for particular Customer you can execute a simple JPQL query like that:
// Customer customer = ...
// EntityManager em = ...
String jpql = "SELECT o FROM Order o WHERE o.owner = :customer";
TypedQuery<Order> query = em.createQuery(jpql, Order.class);
query.setParameter("customer", customer);
List<Order> orders = query.getResultList();
In this way you can execute the code only when you're really sure you want to fetch Customer's orders.
I hope I've understood your problem correctly.
EclipseLink has support for QueryKeys, that allow you to define fields or relationships for querying that are not mapped. Currently there in no annotation support for query keys, but you can define them using the API and a DescriptorCustomizer.
Also you do not need the OneToMany to query on it, just use the inverse ManyToOne to query,
i.e.
Select distinct c from Customer c, Order o where o.customer = c and o.item = :item
Or,
Select distinct o.customer from Order o join o.customer c where o.customer = c and o.item = :item