简体   繁体   中英

Spring + JPA + SQL Views

I've seen that JPA supports using views instead of tables. Our DBA indicated us that we need to use specific views for different kinds of stuff, for instance: One view for SELECT, another for INSERT, another for UPDATE.

Currently, I have one entity and one JPA repository related to a specific table.

My question is: How should I handle this new views? Should I create one entity per view?
Is there a way to make a mapping for one entity to multiple JPA Repositories where each repository is related to a different view?

Thanks!

I was using Spring Boot and had the same issue. I had a view that fetches various fields from various Spring Batch tables to show status of the jobs that users run. After some experimentation the following worked:

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

And the repository definition:

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

If you will use this approach you will have JPA Entity for each view not for the table, your code won't know about how data really stored, and for each Entity you will have Repository, nothing will changed from your side.

Link to documentation about Views: https://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Views

First some clarification: A Repository is a Spring Data thing (and conceptually from Domain Driven Design) JPA doesn't know about Repositories.

I don't think what you want to do can be achieved with JPA. The whole idea of JPA is that you describe how your POJOs and their attributes map to a set of tables and their columns and then let JPA figure out the exact statements to use.

You could set up two persistence contexts one for reading, one for writing, BUT before JPA issues an update statement it will perform a select on the very same table, at the very minimum to verify the id exists. So there goes your separation. Even if there is a way to achieve this it will really bend JPA to its limits (and in my opinion over its limits).

I, recommend one of two approaches:

  • talk to your DBA in order to understand the underlying goal she wants to achieve. This might be achievable in a completely different way.

  • forget about JPA and consider for example MyBatis which might be a much better approach if you need such exact control over your SQL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM