-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Duplicate ID exception on delete statement #281
Comments
After having forced a So perhaps when I did TBH I'm not sure what the semantics of the session is when I try to persist an entity with a unicity constraint error that throws on |
@FroMage, do you have a test case that reproduces this? If so, I can try to look at this next week. |
Entity: @Entity
public class MyPerson {
@Id
@GeneratedValue
public Long id;
public String name;
@Column(unique = true)
public String uniqueName;
public MyPerson() {}
} Test: @Test
public void test() {
// persistAndFlush
MyPerson person1 = new MyPerson();
person1.name = "testFLush1";
person1.uniqueName = "unique";
// get your Mutiny.Session however you like
Panache.getEntityManager()
.flatMap(session -> {
return persistAndFlush(session, person1)
.flatMap(v -> {
MyPerson person2 = new MyPerson();
person2.name = "testFLush2";
person2.uniqueName = "unique";
// FIXME should be PersistenceException see https://github.com/hibernate/hibernate-reactive/issues/280
return assertThrows(PgException.class,
() -> persistAndFlush(session, person2),
"Should have failed");
}).flatMap(v -> {
System.err.println("DONE before delete ?");
return session.createQuery("DELETE FROM MyPerson").executeUpdate();
})
.map(v -> {
System.err.println("deleted "+v);
return "OK";
});
}).await().indefinitely();
}
private Uni<Void> persistAndFlush(Session session, MyPerson person) {
return session.persist(person).flatMap(v -> session.flush()).map(v -> null);
}
private Uni<Void> assertThrows(Class<? extends Throwable> exceptionClass,
Supplier<Uni<?>> f,
String message) {
System.err.println("Asserting "+message+" hoping to get a "+exceptionClass);
Uni<?> uni;
try {
uni = f.get();
}catch(Throwable t) {
uni = Uni.createFrom().failure(t);
}
return uni
.onItemOrFailure().invoke((r, t) -> {
System.err.println("Got back val: "+r+" and exception "+t);
})
.onItem().invoke(v -> Assertions.fail(message))
.onFailure(exceptionClass)
.recoverWithItem(() -> null)
.map(v -> null);
} |
Note that this test was run on ORM with a transaction originally, and if I make it run into a transaction, like this: @Test
public void test() {
// persistAndFlush
MyPerson person1 = new MyPerson();
person1.name = "testFLush1";
person1.uniqueName = "unique";
// get your Mutiny.Session however you like
transactional(session ->
persistAndFlush(session, person1)
.flatMap(v -> {
MyPerson person2 = new MyPerson();
person2.name = "testFLush2";
person2.uniqueName = "unique";
// FIXME should be PersistenceException see https://github.com/hibernate/hibernate-reactive/issues/280
return assertThrows(PgException.class,
() -> persistAndFlush(session, person2),
"Should have failed");
}).flatMap(v -> {
System.err.println("DONE before delete ?");
return session.createQuery("DELETE FROM MyPerson").executeUpdate();
})
.map(v -> {
System.err.println("deleted "+v);
return "OK";
})
).await().indefinitely();
}
private <T> Uni<T> transactional(Function<Mutiny.Session, Uni<T>> work) {
return Panache.getEntityManager().flatMap(session -> session.withTransaction(t -> work.apply(session)));
}
private Uni<Void> persistAndFlush(Session session, MyPerson person) {
return session.persist(person).flatMap(v -> session.flush()).map(v -> null);
}
private Uni<Void> assertThrows(Class<? extends Throwable> exceptionClass,
Supplier<Uni<?>> f,
String message) {
System.err.println("Asserting "+message+" hoping to get a "+exceptionClass);
Uni<?> uni;
try {
uni = f.get();
}catch(Throwable t) {
uni = Uni.createFrom().failure(t);
}
return uni
.onItemOrFailure().invoke((r, t) -> {
System.err.println("Got back val: "+r+" and exception "+t);
})
.onItem().invoke(v -> Assertions.fail(message))
.onFailure(exceptionClass)
.recoverWithItem(() -> null)
.map(v -> null);
} I get slightly different results, in that now the
Which may or may not be the same problem. Looks like the first insert that tripped up the unicity constraint invalidated the transaction? Perhaps it's a hint. |
THanks, I will have a look |
When an exception occurs we want to wrap it in a PersistenceException following the Hibernate ORM behavior.
We expect a PersitenceException.
Wrong issue |
Using
seems to work for me. I think what's happening is that the constraint violation doesn't clear the queue and when you try to execute the query it tries to persist the entity again. @gavinking , @gbadner: I'm still checking but I assume that if this is what's happening then it's a bug, isn't it? |
Also, @FroMage, the exception thrown is going to be a
|
Well when I initially read the problem description I wondered if @FroMage was continuing to use a hosed session after an exception occurred. The rule is that if a session operation throws an exception, you're supposed to obtain a new one. |
Yes, he's using the same session |
@FroMage Could you let me know if it works if you account for those things, please? |
Mmm, but the same works for the ORM version, so are you saying the Quarkus ORM extension automatically renews the session if an exception occurs? |
@DavideD I don't get a CompeltionException because those get unwrapped by Mutiny (or by HR I don't know). |
I guess it might work but I don't think you are supposed to rely on it |
I'm closing this one because reusing the session after an exception is a no-no (even if it might work in some cases). Thanks everybody. |
This might be a user issue, but I don't get it.
I do a bunch of operations in my tests, then in the end I call "delete from Person" to delete all my entities, and I get this exception:
I don't understand how I can get this issue because the
id
field is generated:And I'm not testing duplicate IDs anywhere. This is without a transaction.
I can see in the logs that at this point HR is trying to insert an entity, but my last operation was a
flush
that failed due to a different (not the ID) unicity constraint.I can't seem to figure out how to show the values it's trying to insert, so I'm not sure what entity HR is trying to persist, but I don't think it should be trying to persist anything at this point. This is pretty much a copy of an ORM test that doesn't have this symptom.
The text was updated successfully, but these errors were encountered: