1

2つのエンティティ間に次の1対1(オプション)の関係があります。

@Entity
@Table(name = "HLTH_RQRMT")
public class Requirement
{
    ...
    @OneToOne(mappedBy = "healthRequirement", cascade = CascadeType.ALL)
    private HealthRequirementSystemIdentifier requirementSystemId;

    ...
    public HealthRequirementSystemIdentifier getRequirementSystemId()
    {
        return requirementSystemId;
    }
}

@Entity
@Table(name = "HLTH_RQRMT_SYS_IDNTFR")
public class HealthRequirementSystemIdentifier
{

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "Hlth_Rqrmt_Id", nullable = false)
    private Requirement healthRequirement;
}

要件がデータベースからロードされた後、識別子がチェックされます。

//Load will always return a result (or exception) - works correctly.
Requirement requirement = (Requirement) getSession().load(Requirement.class, id);

//This is where the exception is thrown
if (requirement.getRequirementSystemId() == null)

識別子がある場合、コードはすべての環境で正常に機能します。識別子がない場合は、単体テストおよびローカルで正常に機能します(本番データベースに対するテストで確認されます)。本番環境に識別子がない場合、次のエラーがスローされます。

org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
[Requirement#250583] at
org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:419) at
org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:154) at
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:143) at 
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174) at
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190) at
Requirement_$$_javassist_66.getRequirementSystemId(Requirement_$$_javassist_66.java) at
mypackage.myclass.processResponse(MyServiceImpl.java:244)

optional=falseプロパティをマッピングアノテーションに追加することで、単体テストで上記のエラーをトリガーできます。

単体テストと本番環境で結果が異なる原因は何ですか?プロパティのデフォルト値optionalはtrueです。これが、単体テストで正しく機能する理由です。プロパティを追加しoptional=trueても、単体テストには影響しませんが、本番環境で問題が修正される可能性はありますか?

私は注釈を知って@NotFound(action=NotFoundAction.IGNORE)いますが、それを無視する前に問題の原因を理解したいと思います。

4

1 に答える 1

2

getSession.get()代わりに使用する必要がありますgetSession().load()

load()がキャッシュまたはデータベースでオブジェクトを見つけることができない場合、例外がスローされます。load()メソッドがnullを返すことはありません。オブジェクトが見つからない場合、get()メソッドはnullを返します。

load()メソッドは、実際の永続インスタンスではなくプロキシを返す場合があります。プロキシは、初めてアクセスされたときに実際のオブジェクトのロードをトリガーするプレースホルダーです。プロキシについては、このセクションの後半で説明します。一方、get()はプロキシを返しません。

get()とload()のどちらかを選択するのは簡単です。永続オブジェクトが存在することが確実で、存在しないことは例外的であると見なされる場合は、load()が適切なオプションです。指定された識別子を持つ永続インスタンスがあるかどうかわからない場合は、get()を使用して戻り値をテストし、nullかどうかを確認してください。load()を使用すると、さらに影響があります。アプリケーションは、データベースにアクセスして永続状態を取得することなく、永続インスタンスへの有効な参照(プロキシ)を取得できます。したがって、load()は、キャッシュまたはデータベースで永続オブジェクトが見つからない場合でも例外をスローしない可能性があります。後でプロキシにアクセスすると、例外がスローされます。

于 2013-01-23T23:32:26.540 に答える