Ich habe diese (vereinfacht) Tabellen in meiner DatenbankHibernate Ausnahme: Doppelte Eintrag für Schlüssel ‚primären‘
ich die Tabellen mit diesen (vereinfacht) zwei Klassen zugeordnet haben
UNTERNEHMEN
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name="company_employee",
joinColumns={@JoinColumn(name="company_id")},
inverseJoinColumns={@JoinColumn(name="employee_id")})
@OrderBy("name ASC")
private SortedSet<Employee> employees = new TreeSet<Employee>();
// contructors + getters + setters
}
EMPLOYEE
@Entity
public class Employee implements Comparable<Employee> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(fetch = FetchType.LAZY, optional = true)
@JoinTable(name="company_employee",
joinColumns={@JoinColumn(name="employee_id")},
inverseJoinColumns={@JoinColumn(name="company_id")}
)
private Company company;
@Override
public int compareTo(Employee anotherEmployee) {
return this.name.compareTo(anotherEmployee.name);
}
// contructors + getters + setters + equals + hashcode
}
Ich bin mit einem SortedSet/TreeSet
in Mitarbeiter in Company
definiert die Mitarbeiter nach Namen sortiert zu erhalten.
Das Problem tritt auf, wenn ich die Objekte persistiere. Ich habe gelesen, dass Sie die Beziehung auf beiden Seiten herstellen müssen. Ich setze den Mitarbeiter in der Firma und die Firma im Angestellten, bevor ich die Firma fortsetze. Wenn ich versuche, die bestehen bleiben auszuführen, ich bin zu erhalten die folgende Ausnahme
Exception in thread "main" javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)
at es.rubioric.hibernate.MainTest.main(MainTest.java:43)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:67)
... 1 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1314)
at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:50)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:447)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:333)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:335)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1224)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:464)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2890)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2266)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:230)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
... 1 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '32-80' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3558)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3490)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2109)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2643)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2077)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2280)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2265)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 18 more
Dies ist eine vereinfachte Code, der diese Ausnahme erzeugt. [EDITED begehen Lage nach Kommentar von @NicolasFilotto]
public static void main(String[] args) throws ParseException {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestDB");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Company c = new Company("Nike");
Employee e1 = new Employee("Anthony");
e1.setCompany(c); // line 26
Employee e2 = new Employee("Zenobia");
e2.setCompany(c); // line 28
Employee e3 = new Employee("Chuck");
e3.setCompany(c); // line 30
Employee e4 = new Employee("Bernard");
e4.setCompany(c); // line 32
c.getEmployees().add(e1);
c.getEmployees().add(e2);
c.getEmployees().add(e3);
c.getEmployees().add(e4);
em.persist(c);
tx.commit();
} finally {
em.close();
}
}
Dies sind die SQL-Sätze intern von Hibernate ausgeführt.
Hibernate: insert into Company (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into company_employee (company_id, employee_id) values (?, ?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into company_employee (company_id, employee_id) values (?, ?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into company_employee (company_id, employee_id) values (?, ?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into company_employee (company_id, employee_id) values (?, ?)
Hibernate: insert into company_employee (company_id, employee_id) values (?, ?)
Der gleiche Code funktioniert perfekt, wenn ich 26 Zeilen, 28, 30 und 32 (markiert oben). Aber ich möchte wissen, warum diese Ausnahme erzeugt wird. Warum der doppelte Schlüssel?
Vielen Dank im Voraus.
Versuchen Sie, persistent (c) hinzuzufügen; vor Employee e1 .. –
Hinweis: Ich glaube nicht, dass es eine gute Idee ist, tx.commit() in einem finally-Block –
@NicolasFilotto aufzurufen. Warum ist es keine gute Idee, das Commit in den finally Block zu setzen? – RubioRic