Hibernate Exception - could not locate named parameter - java

i am trying to extract a list of objects from database from entity (table) StudySeries:
#Entity
#Table(name="StudySeries", uniqueConstraints = {
#UniqueConstraint(columnNames = "SeriesInstanceUID")})
public class StudySeries implements Serializable {
...
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "SeId", unique = true, nullable = false)
private Long seId;
#Column(name="SeriesInstanceUID", unique=true, nullable = false)
private String seriesInstanceUID;
...
#ManyToOne
#JoinColumn(name = "StId", referencedColumnName="StId")
private StudyDetails studyDetails;
...
}
This entity is N-1 joined with StudyDetails (on StudyDetails has many StudySeries):
#Entity
#Table(name="StudyDetails", uniqueConstraints = #UniqueConstraint(columnNames = "StudyInstanceUID"))
public class StudyDetails implements Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name="StId", unique = true, nullable = false)
private Long stId;
#Column(name="StudyInstanceUID", unique=true, nullable = false)
private String studyInstanceUID;
...
#OneToMany(fetch = FetchType.LAZY, mappedBy = "studyDetails", cascade = CascadeType.ALL)
private Set<StudySeries> studySeries = new HashSet<StudySeries>(0);
...
}
In my StudySeriesDAOImpl() i am trying to:
#Override
public List<StudySeries> getStudySeriesObjectsByStudyId(Long stId) {
List<StudySeries> results=new ArrayList<>();
Session s=HibernateUtil.openSession();
s.beginTransaction();
String hql = "from StudySeries E where E.studyDetails.stId = stId";
Query query = s.createQuery(hql);
query.setParameter("stId", stId);
results = query.list();
s.getTransaction().commit();
s.close();
log.info(">>>>> list size: " + results.size());
return results;
}
I have also tried the hql query as:
String hql = "from StudySeries E where E.stId = stId";
However i am getting:
org.hibernate.QueryParameterException: could not locate named parameter [stId]
at org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterDescriptor(ParameterMetadata.java:100) at org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterDescriptor(ParameterMetadata.java:100)
at org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterExpectedType(ParameterMetadata.java:106)
at org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:466)
at org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:436)
at com.npap.dao.StudySeriesDAOImpl.getStudySeriesObjectsByStudyId(StudySeriesDAOImpl.java:239)
Any ideas what is wrong?

In the StudySeries class, the id is named as 'seId', not 'stId'.
You should do like this: String hql = "from StudySeries E where E.seId = stId";

Related

Associated entity with OneToOne mapping coming in as null - Hibernate

I have two entities: TableA and TableB. When I fetch TableA, TableB is always null. What am I doing wrong?
This is how I am getting it:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<TableA> criteriaQuery = builder.createQuery(TableA.class);
Root<TableA> from = criteriaQuery.from(TableA.class);
criteriaQuery.select(from);
This is the Query made:
select generatedAlias0 from TableA as generatedAlias0
TableA:
#Entity
#Table(name = "TableA")
public class TableA implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id = null;
#Id
#Column(name = "active", nullable = false)
private Integer active = null;
private Integer parentId = null;
private String myColA = null;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "id", referencedColumnName = "parentId"),
#JoinColumn(name = "active", referencedColumnName = "active")}
)
#Where(clause = "active=1")
private TableB TableB = null;
private Boolean ignorePlanCutoff = null;
}
TableB:
#Entity
#Table(name = "TableB")
public class TableB implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id = null;
#Id
#Column(name = "active", nullable = false)
private Integer active = null;
private Integer parentId = null;
private Boolean colB = null;
}
Both these entities have composite IDs, not showing that here for brevity.

How to write a spring boot jpa specification joining multiple tables

I want to write below query using spring boot specification.
SELECT o.*
from orders as o
inner join user as u on o.user_id = u.id
inner join user_group as ug on u.user_group_id = ug.id
left join order_product op on o.id = op.order_id
left join mobile_order_product mop on op.id = mop.order_product_id
left join mobile_device as md on mop.mobile_device_id = md.id
left join tablet_order_product top on op.id = top.order_product_id
left join tablet_device as td on top.tablet_device_id = td.id
where ug.id = 1
and (md.imei = 123456789 or td.imei = 123456789)
I try to write specification like below but I couldn't find a way to join order_product table.
public static Specification<Order> filterOrdersByGroupIdAndImei(int userGroupId, int imei) {
return (root, query, cb) -> {
Join<Object, User> user = root.join("user");
Join<Object, UserGroup> userGroup = user.join("userGroup");
// how to join order_product and other join tables
Predicate equalPredicate = cb.equal(userGroup.get("id"), userGroupId);
return cb.and(equalPredicate);
};
}
I am going to put answer in my own question.
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "id", nullable = false)
#JsonIgnore
private User user;
#OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
private List<OrderProduct> orderProducts ;
}
#Entity
#Table(name = "order_product")
public class OrderProduct {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "id", nullable = false)
#JsonIgnore
private Order order;
#OneToMany(mappedBy = "orderProduct", fetch = FetchType.LAZY)
private List<MobileOrderProduct> mobileOrderProducts;
#OneToMany(mappedBy = "orderProduct", fetch = FetchType.LAZY)
private List<TabletOrderProduct> tabletOrderProducts;
}
#Entity
#Table(name = "mobile_order_product")
public class MobileOrderProduct {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String mobileCode;
private String mobileNumber;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "id", nullable = false)
#JsonIgnore
private MobileDevice mobileDevice;
#ManyToOne(fetch = FetchType.LAZY)
#JsonIgnore
#JoinColumn(referencedColumnName = "id", nullable = false)
private OrderProduct orderProduct;
}
#Entity
#Table(name = "mobile_device")
public class MobileDevice {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String serialNumber;
private String imei;
#OneToMany(mappedBy = "mobileDevice", fetch = FetchType.LAZY)
#JsonIgnore
private List<MobileOrderProduct> mobileOrderProducts;
}
Here I only included couple of my entity class because then you can understand the table structure correctly
public static Specification<Order> filterOrdersByGroupIdAndImei(int userGroupId, String imei) {
return (root, query, cb) -> {
List<Predicate> list = new ArrayList<Predicate>();
Join<Order, User> user = root.join("user");
Join<User, UserGroup> userGroup = user.join("userGroup");
Join<Order, OrderProduct> orderProduct = root.join("orderProducts", JoinType.INNER);
Join<OrderProduct, MobileDevice> mobileDevice = orderProduct
.join("mobileOrderProducts", JoinType.LEFT)
.join("mobileDevice", JoinType.LEFT);
Join<OrderProduct, TabletDevice> tabletDevice = orderProduct
.join("tabletOrderProducts", JoinType.LEFT)
.join("tabletDevice", JoinType.LEFT);
list.add(cb.equal(userGroup.get("id"), userGroupId));
list.add(cb.or(cb.equal(mobileDevice.get("imei"), imei), cb.equal(tabletDevice.get("imei"), imei)));
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}

Passing Queries from Postgres to JPA

I'm newbie
I'm trying pass this Postgres query to JPA/JPQL
SELECT
DISTINCT(srv.code) AS Serv_Cod,
srv.id AS Serv_id,
srv.description AS Serv_Desc
FROM db.Category AS cat
join db.Classification AS cla ON cat.id = cla.cat_id
join db.Service AS srv ON srv.id = cla.srv_id
WHERE cat.id = 10
ORDER BY srv.id;
Now I want to write the same Query, I have the Entities with the same name Table.
Classification
#Entity
#Table(name = "Classification", schema = "db")
#Audited
public class Classification implements Identifiable<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "srv_id", nullable = true)
private Service service;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cat_id", nullable = true)
private Category category;
....
}
Service
#Entity
#Table(name = "Service", schema = "db")
#Audited
public class Service implements Identifiable<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "code", nullable = false)
private String code;
#Column(name = "description", nullable = false)
private String description;
....
}
I was reading, but I'm very confused...
I don't know how to write the ON for the JOIN, and establish the DISTINCT for a Column/Field.
Long myID = 25L;
this.em.createQuery("SELECT NEW SomeDto(srv.id, srv.code, srv.description)"
+ " FROM Classification cla"
+ "JOIN cla·cat_id cat"
+ "JOIN cla·srv_id srv"
+ "WHERE cat.id = :id"
,BaseObjectDto.class).setParameter("id", myID).getResultList();
Thank you for you valuable Help.
The query is very simple. When you have ToOne relationships you can navigate to the related entity. There is no need to JOIN ON.
Even with ToMany there is no need for the ON because this is already defined in the mapping.
So the query will look like:
SELECT NEW SomeDto(cla.service.id, cla.service.code, cla.service.description)
FROM Classification cla
WHERE category.id = :id

Join queries with JPQL in Spring Data Jpa

I created a left join query with JPQL in spring data jpa but failed in my unit test. There are two entities in the project.
Product entity:
#Entity
#Table(name = "t_goods")
public class Product implements Serializable {
#Id
#GeneratedValue
#Column(name = "id", length = 6, nullable = false)
private Integer id;
#Column(name = "name", length = 20, nullable = false)
private String name;
#Column(name = "description")
private String desc;
#Column(name = "category", length = 20, nullable = false)
private String category;
#Column(name = "price", nullable = false)
private double price;
#Column(name = "is_onSale", nullable = false)
private Integer onSale;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "brand_id")
private Brand brand;
// getter and setter
}
Brand entity:
#Entity
#Table(name = "tdb_goods_brand")
public class Brand implements Serializable {
#Id
#GeneratedValue
#Column(name = "id", length = 6, nullable = false)
private Integer id;
#Column(name = "brand_name", unique = true, nullable = false)
private String name;
#OneToMany(mappedBy = "brand", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Product> products;
// getter and setter
}
And a third class Prod to map the query results to Object:
public class Prod implements Serializable {
private Integer id;
private String name;
private double price;
//private String brandName;
// getter and setter
}
It works fine with this query:
public interface ProductRepository extends JpaRepository<Product, Integer> {
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price) from Product p ")
Page<Prod> pageForProd(Pageable pageRequest);
}
But if I add new property brandName for Prod and refactor the query with left join, it test fails:
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price, b.name) from Product p left join com.pechen.domain.Brand b on p.brand_id = b.id")
Page<Prod> pageForProd(Pageable pageRequest);
The problem seems to be here on p.brand_id = b.id because there is not a brand_id property in Product, it's just a column name. So how can I make this work?
Update:
There turned to be some sytax errors in the JPQL query, just fix it as the following:
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price, b.name) from Product p left join p.brand b")
Page<Prod> pageForProd(Pageable pageRequest);
Besides, it's very troublesome in this way to create another class everytime to map the query results into object(I mean the Prod class). So is there a good way to work with it? Any help would be appreciated.
Instead of p.brand_id = b.id you should do p.brand.id = b.id

JPQL join condition in linked Entity class

I'm using the following SQL to join employees, user_projects and project_master
SELECT DISTINCT usr.user_number,
emp.emp_name
FROM employees emp
LEFT JOIN user_projects usr
ON (emp.user_number = usr.user_number)
JOIN project_master mast
ON (usr.project_id = mast.project_id)
WHERE mast.active = 'Y'
AND emp.user_number = 'SMITH'
In Employee entity, I have the following JPQL defined as namedQuery
#NamedQuery(name = "Employee.findProjects", query = " select DISTINCT u.userNumber,e.empName" +
" from Employee e LEFT JOIN e.userProjectsList u where e.userNumber='SMITH' ")
Not sure how to link UserProjects and ProjectMaster to create a where condition
mast.active = 'Y' in Employee entity's findProjects namedQuery
How to join UserProjects and ProjectMaster in Employee Entity class?
Entities
Entity Employee
#Table(name = "EMPLOYEES")
public class Employee implements Serializable {
#Id
#Column(name = "USER_NUMBER", nullable = false)
private String userNumber;
#Column(name = "EMP_NAME")
private String empName;
#OneToMany(mappedBy = "employee")
private List<UserProjects> userProjectsList;
Entity UserProjects
#Table(name = "USER_PROJECTS")
public class UserProjects implements Serializable {
#Id
#Column(name="PROJECT_ID", nullable = false, insertable = false,
updatable = false)
private String projectId;
#Id
#Column(name="USER_NUMBER", nullable = false, insertable = false, updatable = false)
private String userNumber;
#ManyToOne
#JoinColumn(name = "PROJECT_ID", referencedColumnName = "PROJECT_ID")
private ProjectMaster projectMaster;
Entity ProjectMaster
#Table(name = "PROJECTMASTER")
public class ProjectMaster implements Serializable {
#Id
#Column(name="PROJECT_ID", nullable = false)
private String projectId;
#Column(name="PROJECT_DESCRIPTION")
private String projectDesc;
#Column(name="ACTIVE")
private String active;
select DISTINCT u.userNumber,e.empName from Employee e LEFT JOIN
e.userProjectsList u JOIN u.projectMaster pm
where e.userNumber='SMITH' AND pm.active='Y'
Isn't this work?

Categories