Hibernate multiple subqueries with DetachedCriteria - mysql

I would like write this query into HQL :
select DISTINCT * from transportation transp
inner join price p on p.transportationId = transp.transportationId
where p.sectionId = ( select sec.sectionId from section sec where sec.lineId = ( select l.lineId from line l where l.lineId = 1000000000) )
But don't know write subqueries. I know I must use DetachedCriteria.
An other question:
If we can write this query in native query (using createSQLQuery), how can cast returned objet to Transportation entity ?
Thanks
My entities :
#Entity
#Table(name = "transportation")
public class Transportation implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "transportationId")
private Integer id;
#OneToMany(mappedBy = "transportation", fetch = FetchType.EAGER)
#JsonBackReference(value = "price-transportation")
private Set<Price> prices = new HashSet<Price>();
...
}
#Entity
#Table(name = "price")
public class Price implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "priceId")
private Integer id;
#ManyToOne(optional = false)
#JoinColumn(name = "transportationId")
#JsonManagedReference(value = "price-transportation")
private Transportation transportation;
...
}
#Entity
#Table(name = "section")
public class Section implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sectionId")
private Integer id;
#ManyToOne(optional = false)
#JoinColumn(name = "lineId")
#JsonManagedReference
private Line line;
...
}
#Entity
#Table(name = "line")
public class Line implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "lineId")
private Integer id;
#OneToMany(mappedBy = "line", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JsonBackReference
private Set<Section> sections = new HashSet<Section>();
...
}

I solved my issue by using .addEntity(Transportation.class) like this :
String query = "select DISTINCT * from moyen_transport transp"
+ " join prix_voyage p on p.ID_MoyenTransport = transp.ID_MoyenTransport"
+ " where p.ID_Troncon = ( select t.ID_Troncon from troncon t where t.ID_Troncon = ( select l.ID_Ligne from ligne l where l.ID_Ligne = 1000000000) )";
Query result = getSession().createSQLQuery(query).addEntity(Transportation.class)**;
List<Transportation> results = result.list();

Related

Failed to convert from type [java.lang.Object[]] to type [#org.springframework.data.jpa.repository.Query

I have spring boot project using JPA/Hibernate, MySQL. I have three dao classes that have a many to many relationship.
The Poko classes look like this
Product
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "price")
private Double price;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(
name = "product_extra",
joinColumns = #JoinColumn(name="product_id"),
inverseJoinColumns = #JoinColumn(name="extra_id")
)
private List<Extra> extras = new ArrayList<>();
//constructor getters and setters
}
ProductExtra
#Entity
#Table(name = "product_extra")
public class ProductExtra {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "product_id")
private Integer productId;
#Column(name = "extra_id")
private Integer extraId;
//constructor getters and setter
}
Extra
#Entity
#Table(name = "extra")
public class Extra {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "price")
private Double price;
#ManyToMany(mappedBy = "extras")
private List<Product> products = new ArrayList<>();
//constructor getters and setters
}
The Extra repository with the query
public interface ExtraRepository extends JpaRepository<Extra, Integer> {
#Query("SELECT e.id, e.name, e.price FROM Extra e INNER JOIN ProductExtra pe ON e.id = pe.extraId WHERE pe.productId = ?1")
List<Extra> findExtraById(Integer productId);
}
The mapping in my controller
#GetMapping("/product/{productId}")
public List<Extra>getExtraById(#PathVariable("productId") final Integer productId){
return extraRepository.findExtraById(productId);
}
I am trying to make a many to many query to select The extras in each product, i am however getting this error Failed to convert from type [java.lang.Object[]] to type [#org.springframework.data.jpa.repository.Query the error message surprisingly also contains the results i want. Not sure what am doing wrong
Remove the SELECT clause:
#Query("FROM Extra join e.productExtra WHERE pe.productId = ?1")
Also keep in mind, that you not write an SQL Query, You work on Object, so for join you use the mapped property

Named query join select

I need to get GroupEntity objects which have assigned specific role in RoleGroupEntity Table.
I try to do this like that:
#NamedQuery(name = "GroupEntity.getGIDs", query = "SELECT o FROM RoleGroupEntity u JOIN FETCH u.GroupId o WHERE u.role_id LIKE :role_id")
but I got:
org.hibernate.QueryException: could not resolve property: role_id of: RoleGroupEntity
Entites sample:
#Entity
#Table(name = "group")
public class GroupEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "gid_number")
private Long gid_number;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "GroupId")
private List<RoleGroupEntity> GroupId;
RoleGroupEntity has Composite Key:
#Entity
#Table(name = "role_group")
public class RoleGroupEntity implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private RoleGroupCompositeKey posRGKey;
#MapsId("role_id")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "role_id")
private RoleEntity roles;
#MapsId("group_id")
#ManyToOne
#JoinColumn(name = "group_id")
private GroupEntity GroupId;
Do you know how to make my select query to work?
You can not use the joincolumn you have to use: u.roles.id LIKE :role_id")
#NamedQuery(name = "GroupEntity.getGIDs", query = "SELECT o FROM RoleGroupEntity u JOIN FETCH u.GroupId o WHERE u.roles.id LIKE :role_id")

ManyToMany select query in JPA2(JPQL)

I have two tables: User and Role in ManyToMany relationship.
#Entity
#Table(name = "user")
public class User implements Serializable {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#ManyToMany
#JoinTable(name = "user_role",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
//getters, setters
}
and
#Entity
#Table(name = "role")
public class Role implements Serializable {
#Id
#Column(name = "role_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long roleId;
#Column(name = "role_code")
private String roleCode;
#ManyToMany(mappedBy = "roles")
#JsonIgnore
private Set<User> users;
//getters,setters
}
I want select all users and ALL HIS roles if user have role for example 'ROLE_USER'.
I did it in native sql but i would like to use JPQL or CriteriaQuery.
I tried in JPQL(changing earlier fetching type to EAGER becouse in subquery I can't use join fetch):
public List<User> findUsersByRole(String roleName, int startNumber, int endNumber) {
Query q = em.createQuery("select u from User u join fetch u.roles r WHERE u.userId in (SELECT uu.userId FROM User uu join uu.roles rr WHERE rr.roleCode like :roleName)")
.setParameter("roleName", roleName)
.setFirstResult(startNumber)
.setMaxResults(endNumber);
return q.getResultList();
}
and it works as I want but is it possible without changing Fetching type to EAGER?
Thank you for response.
You can do:
public List<User> findUsersByRole(String roleName, int startNumber, int endNumber) {
Query q = em.createQuery("select u from User u join fetch u.roles join u.roles r WHERE r.roleCode like :roleName")
.setParameter("roleName", roleName)
.setFirstResult(startNumber)
.setMaxResults(endNumber);
return q.getResultList();
}

Hibernate - Join query

I have two classes:
#Entity
public class Tick {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = false)
#JoinColumn(name = "elitesystem_id", referencedColumnName = "id")
private EliteSystem eliteSystem;
private Date createDate;
#ManyToOne(optional = true)
#JoinColumn(name = "commander_id", referencedColumnName = "id")
private Commander commander;
private String address;
and
#Entity
public class Note {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = true)
#JoinColumn(name = "tick_id", referencedColumnName = "id")
private Tick tick;
private String text;
private Date createDate;
I want to select all ticks and get notes if there are any:
Query query = session.createQuery("select t, n from Note n right join n.tick t where t.commander.name = '123'");
List<Object[]> list = query.list();
This returns only Tick objects. What is the correct approach to get the Note information as well in 1 single query?
I could put a reference to a Note into the Tick class, but this doesnt sound right, as there are only a few notes, so the column in the Tick table would mostly be empty.
Create a New class for example:
public class TickNote {
private Tick tick;
private Note note;
public TickNote(Tick tick,Note note){
this.tick=tick;
this.note=note;
Then your query is:
Query query = session.createQuery("select NEW TickNote(t, n) from Note n right join n.tick t where t.commander.name = '123'");
List<TickNote> list = query.list();

Converting SQL query to JPA NamedQuery

I'm trying to implement a Keyword search functionality that returns a List of Keyword entities based on a field text match.
Right now, the query
select * from photo_keywords pk
inner join keywords k on pk.photo_id = k.keyword_id
inner join photos p on pk.keyword_id = p.photo_id
where k.keyword LIKE "%$SOME_SEARCH_VALUE%";
returns all matching photos for a given keyword search. I'd like to have this adapted to a #NamedQuery with the following Entity objects:
#Entity
#Table(name = "keywords")
public class Keyword implements Serializable{
#Id
#Column(name = "keyword_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String keyword;
#ManyToMany(mappedBy = "keywords")
private List<Photo> photos;
//getters and setters
}
and
#Entity
#Table(name = "photos")
public class Photo implements Serializable{
#Id
#Column(name = "photo_id", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "photo_name", nullable = false)
private String photoName;
#Column(name = "photo_path", nullable = false)
private String photoPath;
#Column(name = "upload_date", nullable = false)
private Date uploadDate;
#Column(name = "view_count", nullable = false)
private int viewCount;
#Column(name = "capture_date", nullable = false)
private Date captureDate;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "photo_metadata")
#MapKeyColumn(name = "metadata_name")
#Column(name = "metadata_value")
private Map<String, String> photoMetadata;
#ManyToMany
#JoinTable(name = "photo_keywords",
joinColumns = #JoinColumn(name = "keyword_id"),
inverseJoinColumns = #JoinColumn(name = "photo_id"))
public List<Keyword> keywords;
//getters and setters
}
This creates a join table photo_keywords, rather than a JoinColumn.
What I've tried so far with the Keyword entity:
#NamedQueries({
#NamedQuery(
name = "findKeywordByName",
query = "SELECT keyword from Keyword k WHERE k.keyword = :keyword"
)
})
which is executed via
public Keyword findKeywordByString(String keyword){
Keyword thisKeyword;
Query queryKeywordExistsByName = getEntityManager().createNamedQuery("findKeywordByName");
queryKeywordExistsByName.setParameter("keyword", keyword);
try {
thisKeyword = new Keyword((String) queryKeywordExistsByName.getSingleResult());
} catch (NoResultException e){
thisKeyword = null;
}
return thisKeyword;
}
This returns the Keyword, but with the photos property being null. This is to be expected, since I'm only selecting the keyword property. How can I adapt the SQL query above to a #NamedQuery?