1

私はHibernate+Derbyを初めて使用します...この問題がグーグル全体で言及されているのを見ましたが、適切な解決策を見ていません。

この次のコードはmysqlで正常に機能しますが、derbyでこれを試してみると、例外が発生します。

(各タグには2セットのファイルがあり、その逆もあります-多対多)

Tags.java

@Entity
@Table(name="TAGS")
public class Tags implements Serializable 
{

   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   public long getId()
   {
      return id;
   }

   @ManyToMany(targetEntity=Files.class
   )
   @ForeignKey(name="USER_TAGS_FILES",inverseName="USER_FILES_TAGS")
   @JoinTable(name="USERTAGS_FILES",
         joinColumns=@JoinColumn(name="TAGS_ID"),
         inverseJoinColumns=@JoinColumn(name="FILES_ID"))
         public Set<data.Files> getUserFiles()
         {
      return userFiles;
         }

   @ManyToMany(mappedBy="autoTags",
         targetEntity=data.Files.class)
         public Set<data.Files> getAutoFiles()
         {
      return autoFiles;
         }

Files.java


@Entity
@Table(name="FILES")
public class Files implements Serializable
{
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   public long getId()
   {
      return id;
   }
      @ManyToMany(mappedBy="userFiles",
         targetEntity=data.Tags.class)
   public Set getUserTags()
   {
      return userTags;
   }
   @ManyToMany(targetEntity=Tags.class
         )
         @ForeignKey(name="AUTO_FILES_TAGS",inverseName="AUTO_TAGS_FILES")
   @JoinTable(name="AUTOTAGS_FILES",
         joinColumns=@JoinColumn(name="FILES_ID"),
         inverseJoinColumns=@JoinColumn(name="TAGS_ID"))
   public Set getAutoTags()
   {
      return autoTags;
   }

DBにデータを追加しましたが、Derbyで実行すると、これらの例外が発生します(mysqlを使用しないでください)

例外


SEVERE: DELETE on table 'FILES' caused a violation of foreign key constraint 'USER_FILES_TAGS' for key (3).  The statement has been rolled back.
Jun 10, 2010 9:49:52 AM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not delete: [data.Files#3]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2712)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2895)
   at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:97)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:260)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:613)
   at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
   at $Proxy13.flush(Unknown Source)
   at data.HibernateORM.removeFile(HibernateORM.java:285)
   at data.DataImp.removeFile(DataImp.java:195)
   at booting.DemoBootForTestUntilTestClassesExist.main(DemoBootForTestUntilTestClassesExist.java:62)

私はこれまでダービーを使ったことがないので、私が見逃している残酷なことがあるかもしれません
1)私は何を間違っているのですか?
2)2つのクラス間に2つの多対多の関係がある場合、適切にカスケードする方法はありますか?

ありがとう!

4

1 に答える 1

1

次のコードはMySQLで正常に機能しますが、ダービーでこれを試してみると、例外が発生します。

私の推測では、MySQLで参照整合性を使用していなかったため(つまり、InnoDBエンジンではない)、制約違反は「トリガー」されませんでした。しかし、エラーはそこにあります。

そして実際には、問題はmappedBy、双方向の関連付けの同じ側に、たとえばTags両方に配置する必要があることですManyToMany(そしてそれをから削除しますFiles)。

@Entity
public class Tags implements Serializable {

    @ManyToMany(mappedBy = "userTags")
    @ForeignKey(name = "USER_TAGS_FILES", inverseName = "USER_FILES_TAGS")
    @JoinTable(name = "USERTAGS_FILES", joinColumns = @JoinColumn(name = "TAGS_ID"), inverseJoinColumns = @JoinColumn(name = "FILES_ID"))
    public Set<Files> getUserFiles() {
        return userFiles;
    }

    @ManyToMany(mappedBy = "autoTags")
    public Set<Files> getAutoFiles() {
        return autoFiles;
    }

    //...
}

そして、次のFilesようになります。

@Entity
public class Files implements Serializable {

    @ManyToMany
    public Set<Tags> getUserTags() {
        return userTags;
    }

    @ManyToMany
    @ForeignKey(name = "AUTO_FILES_TAGS", inverseName = "AUTO_TAGS_FILES")
    @JoinTable(name = "AUTOTAGS_FILES", joinColumns = @JoinColumn(name = "FILES_ID"), inverseJoinColumns = @JoinColumn(name = "TAGS_ID"))
    public Set<Tags> getAutoTags() {
        return autoTags;
    }

    // ...
}

これらの変更により、次のテストに合格します(sessionテストメソッドの外部で作成されます)。

@Test
public void removeFiles() {
    Files files = (Files) session.get(Files.class, 1L);

    session.delete(files);
    session.flush();

    Query q = session.createQuery("from Files f where f.id = :id");
    q.setParameter("id", 1l);
    Files result = (Files) q.uniqueResult();
    assertNull(result);
}

そして、次のクエリを生成します。

Hibernate:Filesfiles0_からfiles0_.idをid100_0_として選択します。files0_.id=?
Hibernate:AUTOTAGS_FILESから削除します。ここでFILES_ID =?
Hibernate:userFiles_id =のFiles_TAGSから削除しますか?
Hibernate:id =?のファイルから削除します
Hibernate:files0_.idをfilesfiles0_からid100_として選択します。files0_.id=?

ダービーでテスト済み。

于 2010-06-11T14:22:18.120 に答える