2016-10-09 8 views
1

多対多に関連する2つの単純なテーブルfilerowがあります。 1つのファイルには複数の行が含まれ、1つの行には複数のファイルが含まれます。 row.idとしてJPAで多対多の関係を正しく保持する方法

CREATE TABLE file 
(
    id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT, 
    name VARCHAR(30) DEFAULT '' NOT NULL 
); 
CREATE UNIQUE INDEX file_id_uindex ON file (id); 

CREATE TABLE row 
(
    id BINARY(16) PRIMARY KEY NOT NULL, 
    content TEXT 
); 
CREATE UNIQUE INDEX row_id_uindex ON row (id); 

CREATE TABLE file_row 
(
    file_id INT(11), 
    row_id BINARY(16), 
    CONSTRAINT file_id___fk FOREIGN KEY (file_id) REFERENCES file (id), 
    CONSTRAINT row_id___fk FOREIGN KEY (row_id) REFERENCES row (id) 
); 
CREATE INDEX file_id___fk ON file_row (file_id); 
CREATE INDEX row_id___fk ON file_row (row_id); 

テーブルでのみ一意の行を格納することができるので、私は、行のコンテンツのハッシュを使用します。

とJavaでの私のマッピングされたクラス:私はEntityManagerクラスのpersist()メソッドを使用するエンティティを保存するには

@Getter 
@Setter 
@Entity 
@Table(name = "file") 
public class File implements Serializable { 

    @Builder 
    public File(int id, String name, List<Row> rows) { 
     this.id = id; 
     this.name =name; 
     this.rows = rows; 
    } 

    public File(){ 
    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    @Column(name = "name") 
    private String name; 

    @ManyToMany(cascade = CascadeType.MERGE) 
    @JoinTable(name = "file_row", 
      joinColumns = @JoinColumn(name = "file_id"), 
      inverseJoinColumns = @JoinColumn(name = "row_id")) 
    private List<Row> rows; 
} 

@Getter 
@Setter 
@Entity 
@Table(name = "row") 
public class Row implements Serializable{ 

    public Row() { 
    } 

    @Builder 
    public Row(byte[] id, String content, List<File> files){ 
     this.id = id; 
     this.content = content; 
     this.files = files; 
    } 

    @Id 
    @Column(columnDefinition = "BINARY(16)") 
    private byte[] id; 

    @Lob 
    @Column(name = "content") 
    private String content; 

    @ManyToMany(mappedBy = "rows", cascade = CascadeType.MERGE) 
    private List<File> files; 
} 

新しいファイルに一意の行を追加すると、すべて問題ありません。私は重複行のエラーでファイルを保持しようとした場合でも発生します。私は、テーブルに既にある行を持つファイルを保持する場合

Caused by: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.restapp.entity.Row#[[email protected]] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1664) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1152) 
    at org.jboss.as.jpa.container.AbstractEntityManager.persist(AbstractEntityManager.java:580) 
    at com.restapp.dao.AbstractDao.persist(AbstractDao.java:43) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82) 
    at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93) 
    at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437) 
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64) 
    at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) 
    at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(PooledInstanceInterceptor.java:51) 
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) 
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:254) 
    ... 178 more 

もエラーが発生しています。

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '\xE6t\xDB]\xFA\xF0\xAFz\xD4\xED\xAE\xFC\x84\xD7\x99\xA9' for key 'PRIMARY' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) 
    at com.mysql.jdbc.Util.getInstance(Util.java:408) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) 
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073) 
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009) 
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994) 
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) 
    ... 129 more 

私の問題を解決するのを手伝ってください。

答えて

0

私は解決策を見つけたようです。それは私がやったことだ:

  1. を使用して、新しいファイル(link)を追加するEntityManagerクラスの代わりに、persist()merge()方法。
  2. <property name="hibernate.event.merge.entity_copy_observer" value="allow"/>~persistence.xmlプロパティ(link)を追加します。
関連する問題