2

私の例の完全なエラー行は、「[PersistenceException:org.h2.jdbc.JdbcSQLException:Parameter "#1" is not set; SQL statement:delete from class4 where(class3_id)in(?)[90012-158]]」です。

これは私の単体テストで発生していたので、それを再現するためのテストプロジェクトを作成することにしました。

基本的に、クラス1〜4があり、それぞれが1対多に関連していて、作成してから1、2、3、4、4、3、2、1の順序で削除しようとしていますが、このエラーが発生します。

クラスは番号を除いてすべて同じです(そして最後のクラスにはリストがありません

@Entity
public class Class1 extends Model{

/**
 * 
 */
private static final long serialVersionUID = 4322329984247299024L;

@Id
@GeneratedValue
public Long id;



@OneToMany(mappedBy="class1",cascade={CascadeType.PERSIST, CascadeType.ALL})
private List<Class2> class2s = new ArrayList<Class2>();

public Class2 add()
{
    Class2 class2 = new Class2(this);
    Class2.create(class2);
    return class2;
}


@play.db.ebean.Transactional 
public static void create(Class1 class1) {
    class1.save();
    }



  @play.db.ebean.Transactional 
 public static void delete(Class1 class1) {
      class1.delete();
    }
}

エラーの原因となるアプリケーションコードは次のように実行されます

      Class1 class1 = new Class1();
  Class1.create(class1);
  Class2 class2 = class1.add();
  class1.add();

  Class2.delete(class2);
  Class1.delete(class1);

また、それが起こっていることを示すサンプルアプリケーションを添付しました。誰かが私が間違ったことを指摘できれば、または誰かが私がそれを回避する方法を知っていれば、それがAPIのバグであるなら、私は最も素晴らしいでしょう。

http://stowelly.co.uk/play-2.0.3-persistence-test.zip

ありがとうございました

4

2 に答える 2

2

これはEbeanのバグのようです

http://www.avaje.org/bugdetail-420.html

とにかく、これが問題なく対処されている間の一時的な回避策は、各クラスの削除関数の次のコードです

 @play.db.ebean.Transactional 
     public static void delete(Class2 class2)
  {  
     List<Class3> list = class2.getClass3s();
     for(int i = 0; i < list.size(); ++i)
     {
       Class3.delete(list.get(i));
     }  
     list.clear();
     class2.getClass1().getClass2s().remove(class2);
     class2.delete();
    }
于 2012-08-30T12:52:56.457 に答える
1

@Transactionalエンティティのようなものを使用しないでください。代わりに、これをビジネスロジック/永続性に使用してください。

@Entity
public class A
{
    Long id;
    List<B> bs;

    //...
}

public class DAO
{
    @Transactional
    public void addBtoA(A a, B b)
    {
         b = em.persist(b);
         a = em.find(a);
         a.addB(b);
         em.persist(a);
    }
}

簡単な説明は、トランザクションが存在するため、問題が発生した場合にロールバックできるということです。これは、半分永続化されたもの、たとえばBコミットされたもの、A存在しないものB、DB内の参照されていないエントリを防ぐためです。

于 2012-08-31T06:08:54.417 に答える