3

I want to have many archives inside linf and some archives may have null linf. My essential hibernate annotatations are following:

@Entity
public class Linf {
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    public Set<Archive> getArchive() {
        return archives;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    public long getId() {
        return this.id;
    }
}

@Entity
public class Archive {
    public Archive() {
    }

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    public Linf getLinf() {
        return linf;
    }

    public void setLinf(Linf linf) {
        this.linf = linf;
    }


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    public long getId() {
        return this.id;
    }


}

When I save Linf object via sess.saveOrUpdate(linfHbm), I get

Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Duplicate entry '1' for key 'archive_ID'
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    at $Proxy21.executeUpdate(Unknown Source)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1260)
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:279)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1210)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:399)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    at org.kriyak.utils.ImportLinfs.main(ImportLinfs.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'archive_ID'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2444)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2347)
    at sun.reflect.GeneratedMethodAccessor28.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
    ... 20 more

The last sql command that crashes process is:

insert into Linf_Archive (Linf_ID, archive_ID) values (?, ?)

Both fields in this table are not nullable.

Any idea why this can happen?

PS: I've isolated code that causes crash. Here is simple scenario, that produces the problem:

Session sess = getSessionFactory().getCurrentSession();
sess.beginTransaction();
Archive a = new Archive();
Linf linf1 = new Linf();
Linf linf2 = new Linf();
linf1.setTitle("aa1");
linf2.setTitle("aa2");
linf1.getArchive().add(a);
linf2.getArchive().add(a);
sess.save(linf1);
sess.save(linf2);
sess.getTransaction().commit();

Note that archive has zero linf. May be this is illegal? But what if really want this scheme here?

Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
  • possible duplicate of [How to annotate MYSQL autoincrement field with JPA annotations](http://stackoverflow.com/questions/4102449/how-to-annotate-mysql-autoincrement-field-with-jpa-annotations) – Augusto Nov 09 '12 at 18:39

2 Answers2

3

As I've found out, @ManyToMany relationship is exactly the one that should be used here. If signle object belongs to two different sets, then mentioned exception would happen in case @OneToMany.

Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
0

Please make sure you are using right MySQLDialect,

In addition, when adding Archive to Linf, are you setting the parent object before saving?

    public void add(Archive archive){
         if(this.archives == null){
              this.archives = new HashSet<Archive>();
         }
         archive.setLinf(this); //setting the parent
         this.archives.add(archive);
    }

Same when adding MailSourceFile to Archive? This is required to take care the foreign key population.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73