1

HibernateアノテーションでマップされたUserオブジェクトが正常に機能しています。

例えば

@Entity
public class User implements Serializable {

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

   etc ..
}

次に、Spring 3 MVCを使用した「ユーザーの追加」フォームがあり、このフォームをバックアップするためにコマンドオブジェクトが必要だったため、UserCommandでユーザーを上からサブクラス化しました。UserCommandには、ユーザーエンティティの一部として保存する必要のないWebインターフェイスなどに関連するいくつかの追加機能があります。

例えば

public class UserCommand extends User {

    private String initialAddress;

    etc
}

したがって、私のビュー/プレゼンテーション層は基本的にUserCommandオブジェクトを作成し、ユーザーの詳細を入力してから、コントローラーがこれをservice/dao層に送信して永続化します。UserCommandは( "is-a")ユーザーを拡張するため、daoはUserCommandインスタンスを受け入れ、dao検証チェックに合格します(たとえば、ユーザー名とパスワードが入力されていることを確認してください)。

ただし、hibernateが実際にオブジェクトをデータベース内のエンティティとして永続化するようになると、実際のオブジェクトはUserCommandであることに気付くようです。これは、スーパータイプであるにもかかわらず、マップされたエンティティではありません。

結果として生じるエラーは次のとおりです。

   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でUserのフィールドを複製し、フォームの送信中にUserCommandからUserにすべての値を明示的にコピーする必要がありますか?

4

3 に答える 3

2

データベースとビューエンティティを混在させることは悪い習慣だと思います。これらは異なるレイヤーであり、異なるDTOで動作する必要があります。通常、私は次のパターンを使用して2つのレイヤー間で変換します。

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間の変換に複雑なロジックが必要な場合は、これらのメソッドを変換サービスに移動できます。

これらのエンティティを分割することの利点の1つは、検証です。JSR-303アノテーションを指定して、これらのBeanを検証できます。ほとんどの場合、これらのBeanはUIとDBで異なります。

于 2012-12-12T15:28:19.877 に答える
0

Hoazに同意しました。オブジェクトの各フィールドをDTOからDBに簡単にコピーしたい場合は、Dozerユーティリティを使用できます。

于 2012-12-12T15:36:31.427 に答える
0

サブクラスを明示的に定義できるHibernate3.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
}

編集:
descriminatorを忘れないでください。

<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 に答える