JPQL: Warning: HHH000183, Join query between two entities in different folders - spring-boot

What is the correct way to create Join query between two entities in different folder without using eg. #OneToOne relation ?
I have two entities
First in entity/folder1
package com.test.test.test.model.entity.folder1;
#Entity
#Table(name = "table1")
public class Table1 {
#Column(name = "code", length = 6, updatable = false)
private String code;
}
And second entity in entity/folder2
package com.test.test.test.model.entity.folder2;
#Entity
#Table(name = "table2")
public class Table2 {
#Column(name = "code", length = 6, updatable = false)
private String code;
#Column(name = "postCode", length = 6, updatable = false)
private String postCode;
}
Query in Repository (Query working but return empty response):
#Query("""
SELECT t1 FROM Table1 t1
JOIN com.test.test.test.model.entity.folder2.Table2 t2 ON t1.code = t2.code
WHERE t2.postCode <> ''
""")
Optional<Customer> test1Query();
Warning:
HHH000183: no persistent classes found for query class: SELECT t1 FROM Table1 t1
JOIN com.test.test.test.model.entity.folder2.Table2 t2 ON t1.code = t2.code
WHERE t2.postCode <> ''
I spent a lot of time to fix this but i dont know how.
Thanks for help

Because this repository interface only Customer table use.
For without using eg. #OneToOne relation, you can try use: EntityManager or Criteria API

Related

JPA mapping :Primary key column of one table to non Pk/Fk column of another table

#Entity
#Table(name = "TableA")
public class TableAEntity{
#Id
#Column(name = "RUL_ID"
private Integer rulId;
#Column(name = "COMMENT"
private Integer comment;
#OneToOne
#JoinColumn(name = "RUL_ID" referencedColumnName ="PRNT_ID", insertable=false, updatable=false)
private TableBEntity tableB;
//GETTERS AND SETTERS
}
#Entity
#Table(name = "TableB")
public class TableBEntity{
#Id
#Column(name = "ADD_ID"
private Integer addID;
#Column(name = "PRNT_ID"
private Integer prntId;
//GETTERS AND SETTERS
}
There are 2 DB tables.
TableA with primary key as rulId.
TableB with primary key as addID.
I have to implement a customized JOIN query using JPA native query.
Java Code is:
StringBuilder querySql = "select a.rulId, b.prntId from TableA a JOIN TableB b ON a.rulID = b.prntId"
Query tabQuery = entityManager.createNativeQuery(querySql.toString, TableAEntity.class)
List<TableAEntity> entityList = tabQuery.getResultList();
How to establish this OneToOne(TableA:TableB) relationship when they are not linked with any key(pk/fk).
I am unable to map ResultList to my entity class.Primary key of TableA "rulId" always gets linked to PrimaryKey of TableB "addId", wherein I want to get it associated to "prntId".
Can anyone please help on this.
A couple of things to note:
For JPA query, you have to use createQuery (createNativeQuery is for SQL queries);
#Table(name=...) will define the name of the table in the database but not when you write a JPQL query. For that you can use #Entity(name="..."). In your case, it should be #Entity(name="TableA");
The return value of the query is two fields, not TableAEntity. So passing it as parameter to createQuery is wrong;
It's weird to return a.id and b.id. If you want the entities, you can return a and b.
If there is an association between TableA and TableB, for example:
#Entity(name = "TableA")
public class TableAEntity {
...
#OneToOne
#JoinColumn(referencedColumnName ="PRNT_ID", insertable=false, updatable=false)
public TableBEntity tableB;
}
then you can run the following query:
String jpqlQuery = "from TableA a join fetch a.tableB b";
List<TableAEntity> entityList = entityManager.createQuery(jpqlQuery, TableAEntity.class).getResultList()
entityList.foreach( tableAEntity -> {
TableBEntity tabB = tableAEntity.tableB;
});
If there is no association between TableA and TableB:
String jpqlQuery = "select a, b from TableA a JOIN TableB b ON a.rulID = b.prntId";
List<Object[]> entityList = entityManager.createQuery(jpqlQuery).getResultList()
entityList.foreach( row -> {
TableAEntity tabA = (TableAEntity) row[0];
TableBEntity tabB = (TableBEntity) row[1];
});
But if you really just need the ids, this will work too:
String jpqlQuery = "select a.rulId, b.prntId from TableA a JOIN TableB b ON a.rulID = b.prntId";
List<Object[]> entityList = entityManager.createQuery(jpqlQuery).getResultList()
entityList.foreach( row -> {
Integer tabAId = (Integer) row[0];
Integer tabBId = (Integer) row[1];
...
});
Note that you can change the select and mix the two approaches.
But because there is an association between TableAEntity and TableBEntity, you could rewrite all this as:
String jpqlQuery = "from TableA";
List<TableAEntity> entityList = entityManager.createQuery(jpqlQuery,
TableAEntity.class).getResultList()
entityList.foreach( entity -> {
TableAEntity tabA = entity;
TableBEntity tabB = entity.getTableB();
...
});
With or without the association, you can return from the select clause all the combinations of values you need:
select a, b.addID from ...
select a, b from ...

How to do Custom join with Child Entity for a field in JPA?

Hi i have below two entity tables where LOANS is my parent class and DDL Table class is child . The join is custom join . I have other child tables which am able to join correctly. But for this DDL table i want to try a custom join . I am not sure how i can achieve it . The Oracle Query i am trying to achieve is below . How i can do this . Open for Suggestions if this not the correct way of doing it .
Oracle Query
select dt.DESCRIPTION
from LOANS l,ddl_table dt
where
dt.table_name='master' and dt.field_name='mc'
and SUBSTR(dt.DESCRIPTION, 2, 1) = l.MC_TYPE
and l.LOAN_ID = :LOAN_ID
Parent Entity
#DynamicUpdate
#Data
#NoArgsConstructor
#ToString
#Table(name = "LOANS")
#Entity
public class Loans {
#Id
#Column(name = "LOAN_ID")
private Long loanId;
#OneToOne(cascade = CascadeType.ALL)
#WhereJoinTable(clause = "table_name='master' and field_name='type'")
private DDLTable ddlTable;
// Other child tables.
}
DDL Table Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#ToString
#Table(name = "DDL_TABLE")
#Entity
public class DDLTable {
#Id
#Column(name = "TABLE_NAME")
private String tableName;
#Id
#Column(name = "FIELD_NAME")
private String fieldName;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "FILTER_TYPE")
private String filterType;
}
Do you want to (1) establish an association between Loans and DdlTable, or (2) simply execute the query you posted?
If the former, then only the dt.table_name='master' and dt.field_name='mc' and SUBSTR(dt.DESCRIPTION, 2, 1) = l.MC_TYPE part becomes the join clause. You will then be able to call em.find(Loans.class, loanId) and the Loans.ddlTable will be populated in the result. You'll want sth along the lines of:
#OneToOne
#JoinFormula(formula = "SELECT SUBSTR(dt.DESCRIPTION, 2, 1) FROM ddl_table dt WHERE dt.table_name='master' and dt.field_name='mc'", referencedColumnName = "MC_TYPE")
If the latter, there's no need for the Loans.ddlTable field at all, your query can be translated easily into JPQL:
SELECT dt.description
from Loans l, DdlTable dt
where
dt.tableName='master' and dt.fieldName='mc'
and SUBSTRING(dt.description, 2, 1) = l.mcType
and l.loanId = :LOAN_ID
As a side note, I'd think about mapping SUBSTRING(dt.description, 2, 1) as a virtual column in your DB to make the entity mapping easier. Perhaps even a dedicated view with dt.tableName='master' and dt.fieldName='mc'. You could index SUBSTRING(dt.description, 2, 1) for faster lookup.

HSQL query using limit in join part

I'm new in Spring Boot. I tried to find an answer for my question on SO and google, but I can't find an exact answer for it.
I'm trying to create a function in my Spring Boot JpaRepository class which returns a Customer by id with a limited number of ascending ordered AccountingLogs related to the Customer.
My line of code in JpaRepository:
#Query("select c from Customer left outer join AccountingLog a on a.customer.id = c.id where c.id= :id")
Customer getWithLimitedNumberOfLastTransactions(#Param("id") Long id, #Param("limit") int limit);
The Customer class only with the relevant code:
#Entity
public class Customer {
//...
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#Column(nullable = true)
#JsonManagedReference
private Set<AccountingLog> accountingLogs;
//...
}
The customer class only with the relevant code:
#Entity
public class AccountingLog {
//...
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "customer_id")
#JsonBackReference
private Customer customer;
//...
}
So I'm looking for an HSQL query which selects one customer by id with a specified number (variable named limit) of accounting logs in ascending order (last in first) related to the customer.
Thank you for your help!
You can write a native query in #Query if you are using MySql:
#Query(value="select c from Customer left outer join AccountingLog a on a.customer.id = c.id where c.id= :id limit :limit", nativeQuery = true)
or Oracle:
#Query(value="select c from Customer left outer join AccountingLog a on a.customer.id = c.id where c.id= :id and ROWNUM < :limit", nativeQuery = true)

JPA Join Custom query with OneToMany

I would like to use #Query annotation to create left join query from a entity with a #OneToMany relationship.
Parent entity is :
#Entity
#Table(name="Registration")
public class Registration {
#Column(nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate effect;
#OneToMany(targetEntity=Payment.class, cascade=CascadeType.ALL,fetch = FetchType.LAZY)
#JoinColumn(name="uuid")
private List<Payment> payment;
}
Child :
#Entity
#Table(name="Payment")
public class Payment {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name="uuid", strategy = "uuid2")
#Column(columnDefinition = "BINARY(16)")
private UUID uuid;
}
For DAO, I do like below :
#Query("SELECT p FROM Registration r JOIN r.payment p WHERE r.effect = :effect")
Iterable<Payment> find(#Param("effect") LocalDate effect);
Obviously, its wrong because generated query is :
select payment1_.uuid as uuid1_9_, payment1_.amount as amount2_9_ from registration registrati0_ inner join payment payment1_ on registrati0_.uuid=payment1_.uuid where registrati0_.effect=?
while the relation table has been generated:
For me, the correct query should be something like this :
select p.* from registration r join registration_payment rp on rp.registration = r.uuid join payment p on p.uuid = rp.payment where r.effect = '2015-10-16'
What is the good query syntax please ? Actual query return en empty array.
Finally, I found a solution.
You must describe relation table with #JoinTable :
#JoinTable(
name="registration_payment",
joinColumns = #JoinColumn(name="registration"),
inverseJoinColumns = #JoinColumn(name = "payment")
)
private List<Payment> payment;
Modify #Query not needed :
#Query("SELECT p FROM Registration r JOIN r.payment p WHERE r.effect = :effect")
Generated query is :
select payment2_.uuid as uuid1_9_, payment2_.amount as amount2_9_
from registration registrati0_
inner join registration_payment payment1_ on registrati0_.uuid=payment1_.registration
inner join payment payment2_ on payment1_.payment=payment2_.uuid
where registrati0_.effect=?

Add filter on oneToMany mapped table in hibernate/Spring

I am using hibernate4 and spring3.1 in my current project.
I have two tables with one to many mapping. I am using annotation based mapping.
Mappings are done like this :
public class TableA {
#Id
private Long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "sample_id")
private Set<TableB> tableBList;
// setter getter
}
public class TableB{
#Id
private Long id;
private Long sample_id;
private Date added_date;
}
When I fired query like this :
String hql = "FROM TableA WHERE id = 5";
return sessionFactory.getCurrentSession().createQuery(hql).list();
It will return all the rows from TableB which are mapped for id =5.
But I want to add one more condition like added_date = XXXX.
Is it possible to add filter in query or by any other way on column added_date ?
Yes it is possible from the query :
look at the hql documentation : http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#queryhql
You want something like
String hql = "select a from TableA as a inner join a.tableBList as b WHERE a.id = :id and b.added_date > :after";
Query q = sessionFactory.getCurrentSession().createQuery(hql);
q.setParameter("id", 5);
q.setParameter("after", date);
q.list();

Resources