【问题标题】:JPA mapping views and tables with inheritance具有继承的 JPA 映射视图和表
【发布时间】:2016-01-25 23:13:47
【问题描述】:

我有一个无法更改的数据库设计。数据库具有一对一关系的表和视图。视图包含一些从表中计算出来的额外信息。相关信息是行的状态。为这种关系设置的权限是视图是只读的,因为表具有所有可用的 CRUD 操作。 JPA 是选择映射到此设置的 ORM。该应用程序是一个基本的 CRUD 应用程序,通过检查视图中的状态和其他属性然后插入/更新相应的表来进行一些验证。这是我尝试为这种情况建模的两种方法的示例。我想知道哪个更高效、更易于使用和/或执行此操作的“正确方法”。

选项 1 - 这个选项很好,因为我可以使用 JPA 提供的所有接口与数据库交互。这个选项很糟糕,因为我有时必须加载一个看起来非常多余的表和一个模型,并且每个表有 3 个文件。

    Model.java
    package models;
    // relevant imports
    public abstract class Model {
       // columns that are shared with table and view
    }

    Table.java
    package models;
    // relevant imports
    @entity("table")
    public class Table extends Model {
       // Relationships with other tables 
    }

    View.java
    package models;
    // relevant imports
    @entity("view")
    public class View extends Model {
       // View specific columns ...
       // Relationships with other views
    }

选项 2 - 这个选项很好,因为我只需要加载视图并且每个表都有一个文件。这个选项不好,因为对于 CUD 操作,我必须编写本机 SQL。

    Model.java
    package models;
    // relevant imports
    @entity("view")
    public class Model {
       // All VIEW + table columns
       // All relationships with other models
       // custom SQL to insert update or delete
    }

【问题讨论】:

    标签: java mysql hibernate jpa


    【解决方案1】:

    如果您的所有表都具有相应的视图对象,我会将您的 view 实体指定为模型对象内的一对一关系,并且具有只读访问权限。您可以通过编写不带 setter 的 getter 来做到这一点,因为触发任何类型的 set 然后保存将运行失败的查询。像这样使用继承会使您不得不在一个级别中指定所有列,并且您将不知道哪些列属于哪些表或视图。

        Table.java
        package models;
        // relevant imports
        @entity("table")
        public class Table{
            @OneToOne(mappedBy = "table")
            private View view;
            public string getVariable();
            public string setVaraible();
        }
    
        View.java
        package models;
        // relevant imports
        @entity("view")
        public class View{
           @OneToOne
           @JoinColumn(name = "table_id")
           private Table table;
    
           public string getVariable();
           public string getVariable2();
           public string getVariable3();//etc, No setters.
    
           //alternatively use insertable//updateable=false on all column annotation
           @Column(name="variable_4", insertable =  false, updateable=false)
           public string getVariable4();
        }
    

    将它们全部集中在模型对象中会首先破坏在其中拥有 ORM 的对象,因为现在您必须编写大量 mysql 代码来匹配 ORM 的基本 CRUD 功能。这将是你的冗余。

    如果您以后选择使用继承,则此处不使用继承会将继承作为实际选项打开。当然,每次都加入视图可能对性能不利,具体取决于视图的编写情况,但不将它们全部放在同一个对象中可以在这个意义上提供更大的灵活性。

    【讨论】:

    • 谢谢这个答案很有帮助。作为后续行动,我在表之间有一些多对一关系,我想更新整个表集合,如果表和视图之间的连接会成为性能问题。 EAGER 或 LAZY 获取会更好。我的工作流程是 1. 让视图进行验证 2. 如果验证通过更新相应的表,所以这是我需要 JOIN 发生的步骤
    • 您好,我一直在阅读有关 JPA 的更多内容,偶然发现了 @SecondaryTable 注释,它允许我将两个表映射到一个类,并添加了视图列。如果我在视图特定列中添加 insert=false 和 update=false,这是否与您的模型等效?
    • @user3211617 您可以使用它来实现您提出的次要场景,以及我的 insert/update=false 建议,但这也附带了您每次都将访问视图的规定你使用实体。鉴于您的应用程序是如何构建的,这可能是要走的路,但是如果您要大量访问您的实体以进行纯粹的 crud 操作,例如在 REST 应用程序中,您希望将它们分开。 (例如,当您 POST、PUT 或 DELETE 实体时,您不需要获取视图)
    • 非常感谢您的洞察力,是的,我的应用程序正在访问每个请求的视图 b/c 它需要在执行任何 CRUD 操作之前检查某些特定于视图的列,所以我认为每次加入的开销都是必要的。再次感谢您。
    猜你喜欢
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    相关资源
    最近更新 更多