6

Hibernate とマージで奇妙な問題が発生しています。

問題のクラスの構造は次のようになります。

Project --> CaseWorkerA --|> CaseWorker --|> User

したがって、基本的には、CaseWorkerA への参照を含む Project クラスがあります。これは、CaseWorker のサブクラスであり、これも User のサブクラスです。

コード内:

public class Project {
    [...]
    private CaseWorkerA caseWorkerA;

    @ManyToOne(fetch = FetchType.EAGER)
    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
           org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
    @JoinColumn(name = "CaseWorker_A")
    public CaseWorkerA getCaseWorkerA() {
        return caseWorkerA;
    }
}

次に、ユーザー階層があります。

public class User {
    [...]
}

public class CaseWorker extends User {
    private CaseWorkerStatus status;

    @Enumerated(EnumType.STRING)
    public CaseWorkerStatus getStatus() {
        return status;
    }
    [...]
}

public class CaseWorkerA extends CaseWorker {
    [...]
}

次に、プロジェクトを保存するための Dao クラスのメソッドがあります。

public class ProjectDao {
    [...]
    public Project saveUpdateProject(final Project project) {
        if (project.getId() == null) {
            getSession(false).save(project);
        } else {
            project = (Project) getSession(false).merge(project);
        }
        getHibernateTemplate().flush();
        return project;
    }
}

さて、問題は次のとおりです。

Dao メソッドは、データベースに存在するプロジェクトを受け取ります。このプロジェクトは、ステータスが CaseWorkerStatus.ACTIVE である CaseWorkerA に接続されています (データベースと着信オブジェクトの両方で)。しかし、マージ後、ケースワーカーのステータスは null になります。

格納されるオブジェクトと同様に、値はデータベースでも同じであるため、マージ後も同じままであると予想されます。

(このフィールドのデータベースにはトリガーがありません..)

(代わりに saveOrUpdate を使用するように dao-method を変更しようとしていますが、これで問題が解決したとしても、そもそも何が原因なのか知りたいと思っています)。

アップデート:

そこで、デバッガーをいじってみたところ、次のことがわかりました。 問題の CaseWorker のセッションを照会したところ、ステータス フィールドが設定された状態で表示されました (実際、返されたオブジェクトは、プロジェクトに接続されていたものとまったく同じでした)。

saveOrUpdate を実行してから get を実行すると、ステータス フィールドが設定された CaseWorker が生成されました。ということで、マージ方法に問題がありそうです..

4

1 に答える 1

0

なんとかそれを理解したところ、プロジェクトからユーザーへの2番目のパス(lastChangedByのようなもの)があり、誰かが何らかの奇妙な理由でカスケードを配置することを決定したことが判明しました。そのため、プロジェクトを最後に変更した人が CaseWorker の場合、lastChangedBy はそれを User として参照し、ステータスについて何も知らないため、null が格納されました。

コード:

public class Project {
    private User changedBy;

    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
               org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "changed_by")
    public User getChangedBy() {
        return this.changedBy;
    }
    [...]
}

changedBy として設定されたユーザーは、次のようにデータベースから取得されました。

public class UserDao {
    public User getUser(final String userName) {
        return (User) getSession(false).createQuery("from User u where u.loginName = :username").setParameter("username", userName).uniqueResult();
    }
}

どうやら、取得したユーザーが CaseWorker であっても、CaseWorker に関連するフィールドは取得されません。

とにかく、不必要なカスケードを削除しました。それはすべて良いです:)

于 2012-09-04T12:04:04.900 に答える