Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA/SpringBoot Repository for database view (not table)

Tags:

I'm attempting to create a JPA entity for a view. From the database layer, a table and a view should be the same.

However, problems begin to arise and they are two fold:

  1. When attempting to setup the correct annotations. A view does not have a primary key associated with it, yet without the proper @javax.persistence.Id annotated upon a field, you will get an org.hibernate.AnnotationException: No identifier specified for entity thrown at Runtime.

  2. The Spring Boot JpaRepository interface definition requires that the ID type extends Serializable, which precludes utilizing java.lang.Void as a work-around for the lack of an id on an view entity.

What is the proper JPA/SpringBoot/Hibernate way to interact with a view that lacks a primary key?

like image 309
Paul Nelson Baker Avatar asked Nov 27 '18 21:11

Paul Nelson Baker


People also ask

Does JPA work with views?

Using Spring Data JPA, you can map and query views in almost the same way as database tables. If you compare an SQL statement that selects data from a view with one that selects the same data from a table with the same structure, you will not see any difference.

How do I map a view in JPA?

In JPA you can map to a VIEW the same as a table, using the @Table annotation. You can then map each column in the view to your object's attributes. Views are normally read-only, so object's mapping to views are normally also read-only.

How does JPA repository connect to database?

If we want to use JPA with MySQL database, we need the mysql-connector-java dependency. We'll also need to define the DataSource configuration. We can do this in a @Configuration class or by using standard Spring Boot properties. Spring Boot will automatically configure a data source based on these properties.

Is JPA repository a database?

Spring Data JPA focuses on using JPA to store data in a relational database. Its most compelling feature is the ability to create repository implementations automatically, at runtime, from a repository interface. CustomerRepository extends the CrudRepository interface.


2 Answers

I was exploring that topic too. I ended up using Spring Data JPA Interface-based Projections with native queries.

I created an interface, making sure the UPPERCASE part matches the DB Column names:

public interface R11Dto {     String getTITLE();     Integer getAMOUNT();     LocalDate getDATE_CREATED(); } 

Then i created a repository, for an Entity (User) not related in any way to the view. In that repository i created a simple native query. vReport1_1 is my view.

public interface RaportRepository extends JpaRepository<User, Long> {     @Query(nativeQuery = true, value = "SELECT * FROM vReport1_1 ORDER BY DATE_CREATED, AMOUNT")    List<R11Dto> getR11();  } 
like image 90
Robert Niestroj Avatar answered Sep 23 '22 20:09

Robert Niestroj


1. Create View with native SQL in the database,

create or replace view hunters_summary as  select  em.id as emp_id, hh.id as hh_id from employee em  inner join employee_type et on em.employee_type_id = et.id   inner join head_hunter hh on hh.id = em.head_hunter_id; 

2. Map that, View to an 'Immutable Entity'

package inc.manpower.domain;  import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Subselect;  import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import java.io.Serializable; import java.util.Date;  @Entity @Immutable @Table(name = "`hunters_summary`") @Subselect("select uuid() as id, hs.* from hunters_summary hs") public class HuntersSummary implements Serializable {      @Id     private String id;     private Long empId;     private String hhId;      ... } 

3. Now create the Repository with your desired methods,

package inc.manpower.repository;  import inc.manpower.domain.HuntersSummary; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository;  import javax.transaction.Transactional; import java.util.Date; import java.util.List;  @Repository @Transactional public interface HuntersSummaryRepository extends PagingAndSortingRepository<HuntersSummary, String> {     List<HuntersSummary> findByEmpRecruitedDateBetweenAndHhId(Date startDate, Date endDate, String hhId); } 
like image 41
Janitha Madushan Avatar answered Sep 19 '22 20:09

Janitha Madushan