I have a sql query like this
Select * from DB1.Table1 a left join DB2.Table2 b on a.dCode = b.dCode where bID = 123;
How can I create jpa code for the above query? what would be the params of JpaRepository
public interface TestRepository extends JpaRepository<???, ???> {
#Query("???")
??? myTestQueryCOde(Integer bID);
}
What would be at ???
I am not sure if Spring JPA Data support cross DB queries, but have a look at Cross database joins in JPA
Related
I have two pojo's
Endeavor
{
private Integer id;
private EndeavorPlan currentlyActiveEndeavorPlan;
private Set<EndeavorPlan> endeavorPlans;
}
EndeavorPlan{
private Integer id;
private Endeavor endeavor;
private Date creationTs;
private String status;
}
Query:
If I have currentlyActiveEndeavorPlan in endeavor then return that against their endeavor else I want the oldest creationTs endeavorPlan against their endeavor who does not have "D" status. any suggestions????
I tried this hql query:
SELECT
endeavor.id, COALESCE(endeavor.currentlyActiveEndeavorPlan.id,plans.id)
FROM
Endeavor as endeavor,
IN
(endeavor.endeavorPlans) as plans
WHERE
plans.endeavor.id = endeavor.id
and plans.id in (
SELECT
ep.id
FROM
EndeavorPlan as ep
WHERE
ep.endeavor.id = endeavor.id
and ep.status <> 'D'
ORDER BY
ep.creationTs asc
)
and endeavor.id in (:endeavorIds)
GROUP BY
endeavor.id,plans.id
but its giving me two or more endeavorPlans who have more than one EndeavorPlan in an Endeavor but I only want the oldest creationTs EndeavorPlan against their Endeavor.
Not sure I completely understand your use case, but it seems to me that what you want is a Top-N per category which can't be done efficiently with HQL yet because subqueries do not support limit/offset yet (this changes with Hibernate 6).
I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(Endeavor.class)
public interface EndeavorDto {
#IdMapping
Integer getId();
EndeavorPlanDto getCurrentlyActiveEndeavorPlan();
#Limit(limit = "1", orderBy = "creationTs ASC")
#Mapping("endeavorPlans[status <> 'D']")
EndeavorPlanDto getLatestEndeavorPlan();
#EntityView(EndeavorPlan.class)
interface EndeavorPlanDto {
#IdMapping
Integer getId();
Date getCreationTs();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
EndeavorDto a = entityViewManager.find(entityManager, EndeavorDto.class, id);
This will create a SQL query similar to the following:
select e.id, ep1.id, ep1.creation_ts, ep2.id, ep2.creation_ts
from endeavor e
left join endeavor_plan ep1 on e.active_plan = ep1.id
left join lateral (
select ep2.id, ep2.creation_ts
from endeavor_plan ep2
where ep2.endeavor = e.id
order by ep2.creation_ts asc
limit 1
) ep2 on 1=1
If your database does not support lateral joins, it will create a similar query involving a subquery in the ON clause.
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<EndeavorDto> findAll(Pageable pageable);
The best part is, it will only fetch the state that is actually necessary!
I have written a MySQL query and I'm trying to implement via Hibernate. Please help us to resolve this. My MySQL CTE query:
WITH RECURSIVE employeeCte AS
(
select employee_id, employee_name, manager_id, 1 AS LEVEL from employee where employee_id = ?
union all
select e.employee_id, e.employee_name, e.manager_id, LEVEL + 1 from employee e join employeeCte m
on e.employee_id = m.manager_id
)
select * from employeeCte;
Hibernate code:
interface Employeerepository extends JpaRepository<Employee, String>{
#Query("above query")
List<Object> getEMployeeDetails(String employeeId);
}
CTEs are not yet supported in HQL, but I'm working on changing this for 6.0. In the meantime, you can use the native query approach as suggested by Mark Rotteveel, or you take a look at what Blaze-Persistence can do for you here, which supports CTEs and also comes with a Spring Data integration.
I have this SQL query:
select ts.scorename from content_package cp
join content_package_content_package_components cpcps on cpcps.content_package = cp.id
join content_package_component cpc on cpc.id = cpcps.content_package_components
join tests t on t.id = cpc.assessment
join test_scores ts on ts.tests_id = t.id
where cp.tag = 'C_TS_EN_ABSA_G_'
And want to convert it to JPA, ideally Specifications - is this possible?
you can write this query in JPQL but firs you need to create POJO class of your models. if you are using Intelij idea you can create your models in it by going to persistence section ,right click on your data source and select generate persistence mapping by (hibernate or database schema). after creating models you should change your table names to pojo classes in query and so on ....
In order to get the a record in an SQL table with a name, I am using the following query:
SELECT * FROM User WHERE User.name = name;
And the corresponding Spring JPA method name is the following:
UserEntity findUserByName(#Param("name") String name);
My question is the following:
How can I request a random record from an SQL table?
I know that my SQL query should be the following:
SELECT * FROM User
ORDER BY RAND()
LIMIT 1;
But, what should be the corresponding Spring JPA method name for that?
UserEntity findUserXXXXXXX (XXXXXXX);
JPA supports functions which are defined in specification. You can use native query option or JPA 2.1 function to call database functions which are not directly supported by the JPA specification. You can use #Query annotation in your spring data jpa repository.
Native Query
#Query(value="SELECT * FROM User ORDER BY RAND() LIMIT 1", nativeQuery = true)
UserEntity findUser();
Function
#Query("SELECT u FROM UserEntity u order by function('RAND')")
List<UserEntity> findUser();
You can use list.get(0) to get the single user.
if you want to random a list you can easily do it by using PagingAndSortingRepository and provide a random page number where (page_number < page_count)
e.g
long page_count = (totalRecords / perPage)
//Use PageRequest for PagingAndSortingRepository Pageable object
PageRequest.of(new Random().nextLong(page_count), perPage)
or you can provide the random page number from front_end side
I am working with Hibernate and dto,dao design patterns (Java).
i have an entity class and attribute in it and they are defined with #ManyToOne annotation.
I would like to create a count query and "tell" hibernate "DO NOT JOIN" with #ManyToOne tables
While creating a count query:
(Long) crit.setProjection(Projections.count("id")).uniqueResult();
The sql exceute by hibernate is with left join in it .
Even if i count explicitly on the #Id annotation from the entity class .
The actual query appear is with LEFT JOIN for all the "other tables".
That SQL query build by Hibernate - is not efficient since there is no reason for creating a left join when #ManyToOne is set.
After trying and reading about hibernate i found out about FetchMode
but even when setting FetchMode.LAZY
.setFetchMode("brand", FetchMode.LAZY)
The Sql from hiberante having left join in it.
i have also attached the photo from debug that showing all the SubcriteriaList
which is under projectionCriteria .
How could i tell Hibernate DON'T left join Tables from entity class ?
(without writing SQL query by myself) ?
public Response findAll() {
Criteria crit = getDtoCriteria();
}
public Criteria getDtoCriteria() {
return getDtoCriteria(getDtoClass(), getSession());
}
public Criteria getDtoCriteria(Class clazz, Session session) {
Criteria crit = createEntityCriteria(session);
setProjecttionForDto(crit, true, clazz);
return crit;
}
This all are my Subcriteria
[Subcriteria(bran*******ance:bran*******ance), Subcriteria(buc*****:buc*****), Subcriteria(br****:br****), Subcriteria(dyn***:dyn***), Subcriteria(dyna*****.user:user)]
Try using FetchMode.SELECT instead:
(Long) crit.setFetchMode("brand",FetchMode.SELECT)
.setProjection(Projections.count("id"))
.uniqueResult();