【问题标题】:Spring + JPA + SQL ViewsSpring + JPA + SQL 视图
【发布时间】:2018-04-13 20:38:20
【问题描述】:

我看到 JPA 支持使用视图而不是表。 我们的 DBA 告诉我们,我们需要为不同种类的东西使用特定的视图,例如:一个视图用于 SELECT,另一个用于 INSERT,另一个用于 UPDATE。

目前,我有一个实体和一个与特定表相关的 JPA 存储库。

我的问题是: 我应该如何处理这些新观点? 我应该为每个视图创建一个实体吗?
有没有办法将一个实体映射到多个 JPA 存储库,其中每个存储库都与不同的视图相关?

谢谢!

【问题讨论】:

  • 我对@9​​87654322@ 了解不多,但您所描述的 (specific views for different kinds of stuff) 听起来很像 RESTful API。我可以告诉你,我们有一个单独的视图服务器,并且每个实体都有一个用于一个操作的 API(更新/创建/选择...)。我们为每个实体使用 DTO 模式,以确保我们的服务逻辑和存储库逻辑之间的分离。
  • 为了清楚起见,JPA 与视图没有太大关系。 JPA 用于将您的数据库结构与您的服务逻辑进行映射。存储库是连接到您的数据库的手段,您可能会在渲染视图之前调用多个存储库
  • @jrhee17 我有一个带有 DTO 模式的 RESTful API。我还有一个将 DTO 与实体映射的映射器。问题是实体不会与表相关,因为我必须使用不同的视图进行保存、更新和获取。也许JPA不打算以这种方式使用我真的不知道。

标签: java spring hibernate spring-data-jpa


【解决方案1】:

我在使用 Spring Boot 时遇到了同样的问题。我有一个视图,它从各种 Spring Batch 表中获取各种字段,以显示用户运行的作业的状态。经过一些实验,以下工作:

@Entity
public class Job {
    @Id
    @Column(name = "JOB_INSTANCE_ID")
    private String jobInstanceId;
    @Column(name = "JOB_EXECUTION_ID")
    private String jobExecutionId;
    @Column(name = "JOB_NAME")    
    private String jobName;
    @Column(name = "JOB_TYPE")    
    private String jobType;
    @Column(name = "START_TIME")    
    private Date startTime;
    @Column(name = "END_TIME")    
    private Date endTime;
    @Column(name = "STATUS")    
    private String status;
    @Column(name = "USERNAME")    
    private String username;    

    public String getJobInstanceId() {
        return jobInstanceId;
    }

    public void setJobInstanceId(String jobInstanceId) {
        this.jobInstanceId = jobInstanceId;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }   

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getJobType() {
        return jobType;
    }

    public void setJobType(String jobType) { 
        this.jobType = jobType; 
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getJobExecutionId() {
        return jobExecutionId;
    }

    public void setJobExecutionId(String jobExecutionId) {
        this.jobExecutionId = jobExecutionId;
    }    
}

以及存储库定义:

public interface JobsRepository extends JpaRepository<Job, String> {
    @Query(value = "SELECT JOB_INSTANCE_ID, JOB_EXECUTION_ID, JOB_NAME, JOB_TYPE, START_TIME, END_TIME, STATUS, USERNAME  FROM JOBS_VW", nativeQuery = true)
    List<Job> getAll();
    @Query(value = "SELECT JOB_INSTANCE_ID, JOB_EXECUTION_ID, JOB_NAME, JOB_TYPE, START_TIME, END_TIME, STATUS, USERNAME  FROM JOBS_VW WHERE JOB_INSTANCE_ID=?1", nativeQuery = true)
    List<Job> getJobsByInstanceId(String instanceId);
}

【讨论】:

    【解决方案2】:

    如果您将使用这种方法,您将为每个视图而不是表拥有 JPA 实体,您的代码将不知道数据是如何真正存储的,并且对于每个实体,您将拥有存储库,您这边不会有任何改变。

    关于视图的文档链接: https://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Views

    【讨论】:

    • 所以,现在我有: - 1 个名为“Test”的实体 - 1 个名为“TestJPA”的 JPA 存储库 - 1 个名为“Test”的数据库表 您建议我必须为每个视图?类似于: - 3 个视图(testSelect、TestUpdate 和 TestInsert) - 1 个名为“Test”的 DB 表(我们不关心这个) - 与三个视图(TestSelect、TestUpdate、TestInsert)相关的 3 个实体。 - 3 个 JPA 存储库对吗?
    • 理论上是的,但大多数此类解决方案用于在 UI 中您的数据由多个表组合而成的情况下,而不是复杂的 SQL 查询,您创建单独的视图(或多个视图)来更新数据和用于获取的单独视图。
    猜你喜欢
    • 2017-01-10
    • 2020-11-13
    • 1970-01-01
    • 2018-03-21
    • 2012-07-04
    • 2015-09-21
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多