用于数据库视图的JPA/SpringBoot Repository(不是表)

hpcdzsge  于 2024-01-08  发布在  Spring
关注(0)|答案(5)|浏览(197)

我正在尝试为视图创建一个JPA实体。从数据库层来看,表和视图应该是相同的。
然而,问题开始出现,它们是两方面的:
1.当试图设置正确的注解时。视图没有与之关联的主键,但是如果没有在字段上注解适当的@javax.persistence.Id,您将得到一个org.hibernate.AnnotationException: No identifier specified for entity

  1. Sping Boot JpaRepository接口定义要求ID类型扩展Serializable,这排除了使用java.lang.Void作为视图实体上缺少id的解决方案。
    什么是正确的JPA/SpringBoot/Hibernate方式来与缺少主键的视图交互?
a7qyws3x

a7qyws3x1#

1.在数据库中使用原生SQL创建View,

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.将ViewMap到“不可变的属性”

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.现在用你想要的方法创建仓库,

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);
}

dgenwo3n

dgenwo3n2#

我也在探索这个主题。我最终使用Spring Data JPA基于接口的投影与原生查询。
我创建了一个接口,确保大写部分与DB列名匹配:

public interface R11Dto {

   String getTITLE();

   Integer getAMOUNT();

   LocalDate getDATE_CREATED();
}

字符串
然后我为一个实体(用户)创建了一个存储库,这个实体与视图没有任何关系。在这个存储库中,我创建了一个简单的本地查询。vReport1_1是我的视图。

public interface RaportRepository extends JpaRepository<User, Long> {

   @Query(nativeQuery = true, value = "SELECT * FROM vReport1_1 ORDER BY DATE_CREATED, AMOUNT")
   List<R11Dto> getR11();

}

pzfprimi

pzfprimi3#

我希望这对你有帮助,你可以在你的观点中将它分配给一个统一的值。
我们将视图Map到JPA对象,如下所示:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "my_view")
public class MyView implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "my_view_id")
private Long myViewId;
@NotNull
@Column(name = "my_view_name")
private String myViewName;
}

字符串
然后我们创建一个repository:

import org.springframework.data.jpa.repository.JpaRepository;

public interface MyViewRepository extends JpaRepository<View, Long> {
}

yshpjwxd

yshpjwxd4#

如果你的视图没有候选键,你可以通过创建查询使用类似数据库UUID函数的东西添加一个,然后使用UUID作为实体ID的类型。
如果你需要使你的实体只读,你可以用

@Column(insertable = false, updatable = false)

字符串
或者用org.hibernate.annotations注解你的实体类。如果你的提供者是Hibernate >= 5.2,则不可变。

js5cn81o

js5cn81o5#

关于实体IDMap

如果可以更改视图定义,则可以使用addrownum as column。
它通常是特定于DBMS的,其思想是使表中的行号成为实体的ID。
作为替代方案,您可以使用唯一ID的生成器。UUID是一种可能性。最后,您可以坚持使用原生SQL,同时受益于JPA/Hibernate将原生查询结果Map到表示视图数据的特定类。

关于Spring Data 仓库

如果视图不自然地符合Spring Data Repository的要求,这可能意味着使用视图而不是表不一定适合。
事实上,Spring Data存储库类(如CrudRepositoryJpaRepository)旨在为特定实体类提供开箱即用的CRUD操作和一些额外的处理。
在DBMS方面的视图不包括在您选择它时,但您不会直接更新,插入或删除视图中的任何行。
此外,将这样的Repository bean用于视图会有什么附加价值?您几乎不会使用Spring提供的生成的实现。
在您的情况下,如果您将视图定义为实体,我认为使用JpaTemplate更有意义。
它只是JPA API之上的一层。
关于the documentation
JpaTemplate可以被认为是使用本机JPA API的直接替代方案(通过共享的JPA API引用,如上所述)。主要优点是它可以自动转换为DataTemplate;主要缺点是它在本机JPA API之上引入了另一个薄层。注意,异常转换也可以通过AOP建议实现;请查看PersistenceExceptionTranslationPostProcessor

相关问题