How to get Result From Custom Join query in Spring Boot - java

I have 4 tables
Each of them has Entity class, DTO, and Repository
public interface Interface_A extends JpaRepository< Entity_A, Integer> {
Entity_A findByName(String name);
}
public interface Interface_B extends JpaRepository< Entity_B, Integer> {
Entity_B findByName(String name);
}
all of these functions are working properly functions in the JPA repository.
BUT when I try to join 2 tables it says
Carn't create the bean
please insert proper code to do this
public interface Interface_C extends JpaRepository< Entity_A, Integer> {
Entity_A findByName(String name);
#Query(value = "SELECT a.name,b.name FROM Entity_A a INNER JOIN Entity_B b ON a.id = b.aid )
List<Entity_A> getDataFromJoin(); // insert code here
}
Assume that
two tables have the same name as the entity
Entity_A --> (id,name)
Entity_B --> (id,name,aid)

Related

Best Practice to Update Spring Repository

I have Spring Repo class which look like this :
#Repository
public interface EmployeeRepository
extends CrudRepository<Employee, Long> {
#Query("Select s from Employee s where s.Id = ?1")
Optional<Employee> findEmployeeByID(String Id);
#Transactional
#Modifying
#Query(" How to DO that")
UpdateEmployeeDetails()
}
How to efficiently update the Employee details, as employee tables contains more than 15 fields i can't write a function for each of these fields, how we can generate a query which will have common logic to update
For Example :
If we want to update name only so UpdateEmployeeDetails() will execute this query :
UPDATE Employee SET firstName=UPPER(firstName) WHERE id in :ids
If we want to update name and address :
UPDATE Employee SET firstName=UPPER(firstName), Address = "Address" WHERE id in :ids
How we can do this efficiently as there are may fields so we want to generate query dynamically

java spring Long[] (array) type

If i have the next code
/**
* Spring Data JPA repository for the Event entity.
*/
#Repository
public interface EventRepository extends JpaRepository<Event, Long>{
#Query("SELECT id, name FROM event WHERE id IN (:ids)")
List<EventItem> findEvents(#Param("ids") Long[] ids);
}
And want to use it
Long[] ids = new Long[3];
ids[0] = new Long(1);
ids[1] = new Long(2);
ids[2] = new Long(3);
eventRepository.findEvents(ids);
How to use correctly. I'm a beginner user in Spring-framework. I want to get some records with particulary id-s in the same time.
use the JPA #NamedQuery i.e.
Event Entity
#Entity
#Table(name = "event")
#NamedQuery(name = "Event.fetchEventItem",
query = "SELECT id, name FROM event WHERE id IN (:ids)"
)
public class Event {
....
}
Your Interface
#Repository
public interface EventRepository extends JpaRepository<Event, Long>{
List<EventItem> findEvents(Long[] ids);
}
Interface implements class
#Repository
#Transactional(readOnly = true)
public class EventRepositoryImpl implements EventRepository {
#PersistenceContext
EntityManager entityManager;
#Override
public List<EventItem> findEvents(Long[] ids) {
List<Event> list = new ArrayList<Event>();
Query query = em.createNamedQuery("SELECT c FROM Country c");
Query query = entityManager.createNamedQuery("Event.fetchEventItem", Event.class);
query.setParameter(1, ids);
list = query.getResultList();
// Here You can Prapared List<EventItem>
}
}
JPA provides you keywords inside method names to do this, so in your EventRepository class, add a method by following name:
List<Event> findByIdIn(List<Long> ids);
You can find several keywords inside method names which are wrapped just calling by its format that JPA provides.
REFERENCES
Table 2.3 Supported keywords inside method names ->
https://docs.spring.io/spring-data/jpa/docs/1.6.0.RELEASE/reference/html/jpa.repositories.html

Write HQL UPDATE query with generic type

I have a generic tokenRepository interface :
public interface TokenRepository<T_Token extends Token, T_id> {
#Modifying
#Query("UPDATE T_token as a SET a.revocationReason = :reason WHERE a.id = :id")
void revokeByTokenId (#Param("id") T_id id, #Param("reason") RevocationReason revocationReason);
}
And a specialized repository interface :
public interface CustomerTokenRepository extends Repository<CustomerToken, Long>, TokenRepository<CustomerToken, Long> {}
When I launch the Spring Boot app, hibernate return the following error :
org.hibernate.hql.internal.ast.QuerySyntaxException: T_token is not mapped [UPDATE T_token as a SET a.revocationReason = :reason WHERE a.id = :id]
So my question is : Is it possible and how to use java generic type with HQL ?
Thanks !
Yes it's possible
#Modifying
#Query("UPDATE #{#entityName} as a SET a.userRevocationReason = :reason WHERE a.refreshToken.id = :rid")
void revokeByRefreshToken (#Param("rid") T_id refreshTokenId, #Param("reason") UserRevocationReason userRevocationReason);
Where entity name is #Entity(name = "my_entit_name")

BaseRepository Query Entity List Return List of Object Array

I am using Spring JPA framework with Implementation of Hibernate.
I declared a query in A BaseRepository like below:
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryDslPredicateExecutor<T> {
#Query("select e.id,e.name from #{#entityName} e where e.state=1 and e.name like CONCAT(:name,'%')")
List<T> findIdAndNameByNameStartingWith(#Param("name") String name);
}
And use in a Controller
#RequestMapping("/list/byName")
public HttpApiResponse findAllByNameLike(#RequestParam(defaultValue = "") String name) {
List<Platform> platforms = platformRepository.findIdAndNameByNameStartingWith(name);
return HttpApiResponse.doSuccess(platforms);
}
But When i Debug I found findIdAndNameByNameStartingWith() return List like [['hotel',1],['travel',2]] rather than List<Platform>. Could anyone give me some advice many thanks!
It returns what you ask
select e.id,e.name from #{#entityName} e where e.state=1 and e.name like CONCAT(:name,'%')
try to change to
select e from #{#entityName} e where e.state=1 and e.name like CONCAT(:name,'%')

Accessing multiple entity join query resultset with Spring JPA

I have below 2 entity classes 1.student 2. resluts and I have to return a resultset by executing the below customized query
select s.roll_no , s.first_name, s.age ,r.subject_name , r.marks from student s , results r where s.roll_no= : rollNo and r.marks >70
which gives the result set with combination of both student and result entity. In such scenario how do i write my implementation. I have tried below two approaches
Approach 1 :
public interface GetStudentDetail extends CrudRepository<Student, String> {
#Transactional(readOnly=true)
#Query("select s.roll_no , s.first_name, s.age ,r.subject_name , r.marks from student s , results r where s.roll_no= : rollNo and r.marks >70")
public List<student> getStudentDetails(#Param("rollNo")String rollNo);
}
With the above i was able to get only the student entity values from the resultset and results entity objects were not visible here.
Approach 2:
public interface GetStudentDetail extends CrudRepository<Student, String> {
#Transactional(readOnly=true)
#Query("select s.roll_no , s.first_name, s.age ,r.subject_name , r.marks from student s , results r where s.roll_no= : rollNo and r.marks >70")
public List<Object[]> getStudentDetails(#Param("rollNo")String rollNo);
}
By this, i created one more VO class with both the entity variable and i manually set to those object by accessing to it position like below
List<StudentResultVo>studtVoObjList = new ArrayList<StudentResultVo>();
for (Object[] resObj : resultSetList) {
StudentResultVo studtVO = new StudentResultVo();
if (resObj[0] != null) {
studtVO.setRollNo(resObj[0].toString().trim());
}
//.First name
//.Age
if (resObj[3] != null) {
studtVO.setSubName(resObj[3].toString().trim());
}
//.Marks
studtVoObjList.add(studtVO);
}
i knew the above approach is not a good coding practice. Is there any way to achieve solution to this problem.
Thanks.
first create new interface and declare your method
public interface GetStudentDetailCustom {
public List<Object[]> getStudentDetails(String rollNo);
}
and second create class GetStudentDetailImpl and implement the interface
public class GetStudentDetailImpl implements GetStudentDetailCustom {
#PersistenceContext
private EntityManager entitymanager; // I use entity manager also you want to use inject SessionFactory etc..
#Override
public List<Object[]> getStudentDetails(String rollNo) {
String queryString = "SELECT s.roll_no , s.first_name, s.age ,r.subject_name , r.marks FROM student s "
+ ", results r WHERE s.roll_no= :rollNo and r.marks > 70";
Query query = entitymanager.createQuery(queryString);
query.setParameter("rollNo", rollNo);
return query.getResultList();
}
}
and refactor your repository like this
public interface GetStudentDetail extends CrudRepository<Student, String>, GetStudentDetailCustom {}
and finaly use inject GetStudentDetail in your service class and call getStudentDetails method
Example use in your service layer :
#Autowired
private GetStudentDetail getStudentDetail;
getStudentDetail.getStudentDetails(String rollNo);
reference answer : How to add custom method to Spring Data JPA
and spring reference : http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behaviour

Categories

Resources