| Consider a simple entity Node with two properties:
- name (required with a @NotNull and the db column is not allowing nulls)
- label (optional and the db column is allowing nulls)
Then consider this test:
@Test
public void test1()
{
accept(em ->
{
Node n = new Node();
em.persist(n);
n.setName("node-1");
n.setLabel("label-1");
});
}
test1 will fail with:
The incoherence is in the fact that no consistent behavior is met. A consistent behavior is either one:
- a javax.validation.ConstraintViolationException (for @NotNull) should be thrown (on persist or flush/commit)
- or test1 should pass
Supposing that the expected behavior is a validation exception being thrown, the validator is executed on the entity on flush/commit time, but at that time the entity has the "name" set. Then, this leads to an out-of-sync between the entity being validated and the generated statement to be executed, making validation return a false positive. To show it, consider a second simple test:
@Test
public void test2()
{
accept(em ->
{
Node n = new Node();
em.persist(n);
});
}
Correctly, this is failing with:
On the other hand, supposing that the expected behavior is that test1 should pass, the incoherence is due to statement generation time. To show it, consider a second simple test:
@Test
public void test3()
{
accept(em ->
{
Node n = new Node();
n.setName("node-3");
em.persist(n);
n.setLabel("label-3");
});
Node n = apply(em -> em.createQuery("select x from Node x", Node.class).getSingleResult());
Assert.assertEquals("label-3", n.getLabel());
}
Even if the test passes, two statements are generated (and executed).
I suppose the first statement is generated on persist and the second on flush/commit; but, in this case, I'm expecting a single insert statement generated on flush/commit time and immediately after the entity has been validated. In conclusion, I see to possible solutions:
- run the validator inside persist()
- postpone statements generation to flush/commit time
I will upload a test case as soon as I can. Thank you. |