1

我有一个使用休眠注释映射的用户对象,工作得很好。

例如

@Entity
public class User implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long userId;

   etc ..
}

然后我有一个使用 Spring 3 MVC 的“添加用户”表单,我需要一个命令对象来支持这个表单,所以我在 UserCommand 中从上面对用户进行了子类化。UserCommand 上有一些与 Web 界面等相关的额外内容,不需要保存为 User 实体的一部分。

例如

public class UserCommand extends User {

    private String initialAddress;

    etc
}

因此,我的视图/表示层基本上创建了一个 UserCommand 对象,填写用户详细信息,然后控制器将其提交给服务/dao 层以进行持久化。由于 UserCommand extends ("is-a") User dao 接受 UserCommand 实例并通过 dao 验证检查(例如,确保已填写用户名和密码)。

但是,当休眠实际上将对象作为实体持久保存在数据库中时,它似乎意识到实际对象是一个用户命令,它不是一个映射实体,即使它的超类型是。

产生的错误是;

   org.hibernate.MappingException: Unknown entity: com.example.UserCommand
       org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:691)
       org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1494)
       org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:202)
       org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:531)
       org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
       org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
       org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
       org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
       org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)

有没有办法解决这个问题?我似乎是一件显而易见的事情,表单正在填写一个用户,所以只需使用用户的扩展名(即 UserCommand)作为表单的支持命令对象。

还是我将不得不打破继承,在 UserCommand 中复制用户的字段,并在表单提交期间将所有值从 UserCommand 显式复制到 User 中?

4

3 回答 3

2

我认为混合数据库和视图实体是一种不好的做法。这些是不同的层,它们应该在不同的 DTO 上运行。通常我使用以下模式在两层之间进行转换:

public class UserCommand {
    public static UserCommand fromUser(User user) {
        UserCommand command = new UserCommand();
        // fill UserCommand fields
        return command;
    }

    public void toUser(User user) {
        // fill User fields
    }
}

如果视图和数据库 DTO 之间的转换需要一些复杂的逻辑,您可以将这些方法移至转换服务。

拆分这些实体的一个好处是验证。您可以指定 JSR-303 注释来验证这些 bean,并且在大多数情况下,它们对于 UI 和 DB 会有所不同。

于 2012-12-12T15:28:19.877 回答
0

我刚刚在 Hibernate 3.6 中遇到了这个问题,你可以显式地定义一个子类。

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html

使用 xml,您可以:

<subclass name="DomesticCat"
          discriminator-value="D">
   <property name="name" type="string"/>
</subclass>

或带注释:

@Entity @DiscriminatorValue("D")
public class DomesticCat extends Cat {
   //class implementation here
}

编辑:
不要忘记鉴别器。

<discriminitor insert="false" formula="'C'" />

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, insert=false)
@DiscriminatorFormula("'C'")
@DiscriminatorValue("C")
public class Cat { ... }
于 2013-03-12T22:18:27.027 回答
0

同意霍兹。如果您想轻松地将对象的每个字段从 DTO 复制到 DB,您可以使用Dozer实用程序。

于 2012-12-12T15:36:31.427 回答