次の 2 つのコードを分析して、コミット時に最初のコードが主キー違反で失敗し、2 番目のコードが失敗しない理由を教えてください。
コミット時に失敗するコード:
try{
Query q = em.createQuery("DELETE FROM Puntaje");
q.executeUpdate();
//em.getTransaction().commit();
//em.getTransaction().begin();
Iterator it = l.iterator();
while(it.hasNext()){
DataPuntaje dp = (DataPuntaje)it.next();
Cliente c = new Cliente(dp.getCliente());
Puntaje p = new Puntaje(dp.getPuntaje(),c);
c.agregarPuntaje(p);
em.merge(c);
}
System.out.println("test1");
em.getTransaction().commit();
System.out.println("test2");
}
正常に動作するコード:
try{
Query q = em.createQuery("DELETE FROM Puntaje");
q.executeUpdate();
em.getTransaction().commit();
em.getTransaction().begin();
Iterator it = l.iterator();
while(it.hasNext()){
DataPuntaje dp = (DataPuntaje)it.next();
Cliente c = new Cliente(dp.getCliente());
Puntaje p = new Puntaje(dp.getPuntaje(),c);
c.agregarPuntaje(p);
em.merge(c);
}
System.out.println("test1");
em.getTransaction().commit();
System.out.println("test2");
}
唯一の違いは、最初のものは削除クエリをコミットせず、代わりに最後にまとめてコミットすることです。Cliente と Puntaje は cascade = ALL の 1:N 双方向の関係です。Cliente の挿入されたすべてのインスタンスは同じ ID を持っていますが、マージは最初のインスタンスが永続化された後に挿入するのではなく、更新するのに十分スマートである必要がありますが、最初の例では失敗しているようで、説明が見つかりません。また、H2組み込みデータベースを使用しています。
また、追加したいのですが、Cliente 値が既に挿入されている場合、最初のコードは正常に機能します。これは、テーブルが実際に空であり、削除が実際に何もしていない場合に失敗します。
これは私が得るエラーです:
Internal Exception: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_5 ON PUBLIC.CLIENTE(NICK)"; SQL statement:
INSERT INTO CLIENTE (NICK) VALUES (?) [23505-169]
Error Code: 23505
Call: INSERT INTO CLIENTE (NICK) VALUES (?)
bind => [cbaldes]
Query: InsertObjectQuery(Clases.Cliente@21cd5b08)
javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.2.v20100323-r6872): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_5 ON PUBLIC.CLIENTE(NICK)"; SQL statement:
INSERT INTO CLIENTE (NICK) VALUES (?) [23505-169]
Error Code: 23505
Call: INSERT INTO CLIENTE (NICK) VALUES (?)
bind => [cbaldes]
Query: InsertObjectQuery(Clases.Cliente@21cd5b08
)
これらはテーブルです:
@Entity
public class Puntaje implements Comparable, Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private int total;
@ManyToOne(cascade=CascadeType.ALL, optional = false)
@JoinColumn(name="NICK")
private Cliente cliente;
@Entity
public class Cliente implements Serializable {
@Id
private String nick;
@OneToMany(cascade=CascadeType.ALL, mappedBy="cliente")
private List<Puntaje> puntajes;