扩展表的 JPA 映射视图

Dem*_*urg 2 mapping hibernate jpa view

这类似于带有继承的 JPA 映射视图和表,但由于接受的答案不能满足我,我决定提出自己的问题。

我有一个基础类,它包含所有实体的公共字段

@MappedSuperclass
@Access(AccessType.FIELD)
public abstract class CommonFields{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;
   (...)
}
Run Code Online (Sandbox Code Playgroud)

假设我有一个名为 Table 的实体

@Entity
@Table(name = "my_table")
public class Table extends CommonFields{
(..)
}
Run Code Online (Sandbox Code Playgroud)

这对我来说非常有效。我创建了视图,它将一列添加到my_table. 我是这样映射的:

@Immutable
@Entity
@Table(name = "my_table_plus_view")
public class TableView extends Table{
(..)
}
Run Code Online (Sandbox Code Playgroud)

TableView只读的。这很简单Table带有用于演示目的的附加信息。

此应用程序在 Tomcat 和 Postgres DB 上运行。服务器启动时没有错误,但是当我尝试从视图中获取所有记录时,我收到一个错误,即我的Table不包含DTYPE列。我知道它是什么以及它是如何工作的,但因为我不需要它,所以我不想要它。

我想像Table现在一样读/写我的,但我不知道如何映射我的TableViewJPA 查询可以使用它。我做了一些努力,InheritanceType但没有成功。如果我从Tableto复制所有字段,TableView那么我的应用程序将按预期运行,但这不适合我。如何映射我的视图以便我可以使用继承?

Ala*_*Hay 6

您可以将一个实体映射到 2 个表(或者在您的情况下是一个表和一个视图)。您可以使用@SecondaryTable. 视图的列然后成为实体表的属性,可以像其他任何列一样进行查询。

为了确保不变性,您可以标记可以使用insertableupdatable属性的列@Column

@Entity
@Table(name = "my_table")
@SecondaryTable(name = "my_table_plus_view")
public class Table extends CommonFields{

     @Column(name="col_from_view", table="my_table_plus_view", 
           insertable=false, updatable = false)
     private String someField;
}
Run Code Online (Sandbox Code Playgroud)

https://en.wikibooks.org/wiki/Java_Persistence/Tables#Multiple_tables

在这种情况下,您的应用程序只处理一个实体。

另一种方法是创建一个指向视图的新实体,并使用@OneToOne. 只要这种关系始终存在(即标记为optional=false),那么这种方法的好处是仅按需加载视图数据,而使用该@SecondaryTable选项将在每次加载时执行连接。您模型的客户端仍然只能处理一个实体,因为您不需要将第二个实体暴露给外界:

@Entity
@Table(name = "my_table")
public class Table extends CommonFields{

   //can be lazily loaded only when optional = false
   //see: http://stackoverflow.com/questions/17987638/hibernate-one-to-one-lazy-loading-optional-false
   @OneToOne(optional = false)
   @JoinColumn(name = "x")
   private TableView tableView;

   public int getCalculatedValue(){
        return tableView.getCalculatedValue();
   }
}


@Entity
@Table(name = "my_table_plus_view")
public class TableView{

    private int calculatedValue;
}
Run Code Online (Sandbox Code Playgroud)

在另一种情况下,您可以使用上面尝试过的继承。然后,您的应用程序将公开 2 个实体 Table 和 TableView。由于您有 2 个单独的表,因此您需要表明您想要使用 Joined 继承策略。这是您的代码中缺少的一点:

https://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Joined.2C_Multiple_Table_Inheritance

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name = "my_table")
public class Table extends CommonFields{

}


@Entity
@Table(name = "my_table_plus_view")
public class TableView extends Table{

}
Run Code Online (Sandbox Code Playgroud)

使用 Joined 策略,Hibernate 不需要鉴别器列。