【问题标题】:jpa persist non-entity class inheritance @entityjpa坚持非实体类继承@entity
【发布时间】:2013-11-14 08:28:06
【问题描述】:

我在我的EJB 中创建了entities包装器。在这个 wrapper 中,我有我的 business-logic 和我的 validations 共同点用于 entity。我想知道如何将我的 wrapper 发送到 CRUD(但我不希望我的 wrapper 成为@Entity)。

有什么想法???

【问题讨论】:

    标签: inheritance jpa wrapper business-logic


    【解决方案1】:

    最好不要将您的 EJB 用作包装器,而是使用其他具有特定目的的 java 类来包装实体。

    包装类应该包装一个实体,因此它应该是一对一的关联(不要与 jpa 混淆,我的意思是 java 关联/组合)。所以基本上你遵循装饰器模式。

    然后你创建你需要的所有方法,拥有与你要包装的实体相同的方法真的很有帮助。然后在方法体中调用你要包装的实体实例的相应方法。

    示例

    @Entity
    public class Person {
    
        @Column(name = "ID")
        private Long id;
        @Column(name = "FIRST_NAME")
        private String firstName;
        @Column(name = "LAST_NAME")
        private String lastName;
    
        public String getFirstName(){
          return this.firstName;
        }
    
        public void setFirstName(String firstName){
          this.firstName = firstName;
        }
    
        public String getLastName(){
          return this.lastName;
        }
    
        public void setLastName(String lastName){
         this.lastName = lastName;
        }
    }
    
    public class PersonWrapper{
      private Person person;
      private String someCalculatedField;
      public PersonWrapper(Person person){
        this.person = person;
      }
    
      public Person getPerson(){
        return this.person;
      }
    
      public void setPerson(Person person){
        this.person = person;
      }
    
      public String getFirstName(){
        /* possibly do transformations */
        return person.getFirstName();
      }
    
      public void setFirstName(String firstName){
        /* possibly do validations, transformations*/
        person.setFirstName(firstName);
      }
    
      public String getSomeCalculatedField(){
      /*do stuff with person or other entities as well and populate the calculated field,
        then return it
      */
        return this.someCalculatedField;
      }
    
    
    }
    

    也许不清楚,但是在您完成 CRUD 函数或对包装器实例的任何其他操作之后,为了通过 jpa 持久化您的更改,您需要检索 jpa 实体(即 person 在您的情况下来自包装器的方法 getPerson() ) 并调用 persistmergeremove 或对该实例的任何内容。

    编辑

    基于 cmets,我想明确表示,让包装器从实体继承只会有利于将非 jpa(例如 CRUD UI)代码与包装器本身分离,例如通过调用 Person person = new PersonWrapper(personEntity); 而不是PersonWrapper person = new PersonWrapper(personEntity);.

    即使在继承之后,也必须重写包装器中的方法,因为包装器的方法体调用的是包装实例上的代码,而不是包装器本身上的代码。不覆盖方法将调用包装器本身的继承方法。后者是一个错误有两个原因,

    1.数据从错误的实例中存储/检索(包装器不是包装的实体)

    2.data 不应该存储在包装器中,因为它不能在 jpa 函数中使用,因为它不是实体(那里没有 jpa 继承),只能使用包装的实例。此外,包装器并非来自托管 jpa 上下文,因此它没有与持久性相关的数据。

    【讨论】:

    • 你能写个小例子吗?
    • 我想要包装器扩展实体,因为在可延展性之后只更改@entity 中的东西而没有逻辑业务并且您不需要记住更改包装器。有用吗?
    • @MathewRock 很好,当实体更改时,包装器总是需要更改,因为您可以看到它的方法有自己的逻辑。如果您在包装器中继承并跳过实体方法的实现,则从包装器调用实体方法将产生错误的结果,因为它将存储或使用来自错误实例的数据*(将在回答中解释)。但是,您可以出于另一个原因扩展实体,以使使用包装器的其余非 jpa 相关代码(即 UI CRUD 代码)与包装器的耦合更少,并在 Person p = new PersonWrapper() 之类的代码中使用它。
    • 接口可以实现Entity和Wrapper吗?
    • @MathewRock 确定它在你的系统上下文中是否有意义,在 oop 继承术语中。但同样只是为了解耦,这些方法必须如上所述被覆盖。
    猜你喜欢
    • 2011-09-04
    • 2013-12-04
    • 2018-07-25
    • 2015-08-02
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多