扩展DTO对象的更好解决方案(Java,Hibernate)

时间:2012-12-28 16:47:54

标签: java hibernate hibernate-mapping

我使用EmailAlert bean作为DTO来通过Hibernate获取数据。 所以,我的类只包含我在DB中的字段。 但在某些情况下,我需要在EmailAlert中添加其他字段来保存中间数据。例如,“标题”字段 - 将在java侧计算,取决于用户区域设置,时间等。

所以,我有一些变种来解决这个问题。

  1. 向EmailAlert bean添加其他属性(例如:caption),但不要将其映射到DB表的任何字段。 缺点:在这种情况下,我们不得在hashCode()和equals()中使用“caption”属性,因为:

    • 它确实没有问题 - 字段只包含中间数据
    • 我不确定它不是缓存和Hibernate本身问题的原因。 我认为拥有类的属性是非常难看的,但是不要在equals()和hashCode()方法中使用它。
      将来有人可能会混淆这种逻辑。
  2. 通过添加“caption”属性将EmailAlert扩展为EmailAlertExt。以及将EmailAlert作为参数的构造函数。
    但是在这种情况下,我不确定水下石头,以防万一将EmailAlert再次存入DB中作为EmailAlertExt bean。

  3. 将EmailAlert扩展为EmailAlertExt2并添加“caption”属性并对原始对象进行引用。在这种情况下,EmailAlertExt2将表现为原始的EmailAlert,但具有我们需要的附加属性。如果我们保存EmailAlert,我们可以调用EmailAlertExt2的getOriginalValue(),它将返回对原始对象的引用。 缺点:编码太多了:))

  4. 伙计们,哪些解决方案更好?可能有人有其他建议吗?

3 个答案:

答案 0 :(得分:2)

使用'@Transient'它不会映射到db hibernate会忽略这个字段

答案 1 :(得分:1)

仅仅因为想要分隔映射字段和非映射字段而扩展模型对象不是一个好主意。一个好的指导方针是问自己问题" EmailAlert和EmailAlertX之间的区别是什么,我可以清楚地定义我将使用其中一个的情况吗?"。如果你不能干净地回答这个问题,或者你意识到你总是在父类上使用你的子类,那么这肯定表明父类应该是抽象的,或者你有太多类。

在您的特定情况下,在同一个类上同时具有映射和非映射属性更为有意义,并标记非映射属性,以便您的ORM提供程序不会尝试处理它们。您可以通过将这些属性注释为@Transient来实现此目的。

public class EmailAlert implements Serializable {
   @Id
   private Long id;

   @Column(name = "recipient")
   private String recipient;

   @Transient
   private transient String caption;

   // Constructor, Getters/Setters, etc
}

另外,关于你对hashcode / equals方法的评论。您不应该也不应该在这些方法中包含Java Bean的每个属性。仅包含以下属性:

  • 要求唯一标识对象
  • (公平地)保证在对象的生命周期中具有相同的值

答案 2 :(得分:0)

听起来,目前您需要的EmailAlert对象是业务对象,因为“中间数据”和“在Java端计算”位。

也许使用EmailAlertDto对象填充EmailAlertBusiness的字段,并将额外的标题字段和方法存储在业务对象中。