Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA Entity Validation

Ok, I'm trying to setup an application in a Java EE Container. I use JPA for persistence and I also use the javax.validation.constraints.* constraints. By default the container validate the entities during the @PrePersist and @PreUpdate lifecycle events and it's good for me, but how do I handle the ConstraintViolationException?

I can't find any docs on it, any suggestion is welcomed.

like image 469
s.susini Avatar asked Jul 23 '10 23:07

s.susini


People also ask

What is JPA Validator?

Data validation is a common task that occurs in all layers of an application, including persistence. The Java™ Persistence API (JPA) 2.0 provides support for the Bean Validation API so that data validation can be done at run time.

How do you validate an attribute in a entity that stores email ID?

You can use @PrePersist Callback event in your entity to valdiate the email before saving it to database. Or you can make a setter method in your Entity and validate the data in setter method. Show activity on this post. You can create a custom constraint.

How does Bean Validation work?

Very basically, Bean Validation works by defining constraints to the fields of a class by annotating them with certain annotations.

What is @valid annotation in Spring boot?

The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.


1 Answers

Well, you could catch it :) Here is an example (from a unit test):

public class CustomerTest {
    private static EntityManagerFactory emf;
    private EntityManager em;

    @BeforeClass
    public static void createEntityManagerFactory() {
        emf = Persistence.createEntityManagerFactory("MyPu");
    }

    @AfterClass
    public static void closeEntityManagerFactory() {
        emf.close();
    }

    @Before
    public void beginTransaction() {
        em = emf.createEntityManager();
        em.getTransaction().begin();
    }

    @After
    public void rollbackTransaction() {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        if (em.isOpen()) {
            em.close();
        }
    }

    @Test
    public void nameTooShort() {
        try {
            Customer customer = new Customer("Bo");
            em.persist(customer);
            em.flush();
            fail("Expected ConstraintViolationException wasn't thrown.");
        } catch (ConstraintViolationException e) {
            assertEquals(1, e.getConstraintViolations().size());
            ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();

            assertEquals("name", violation.getPropertyPath().toString());
            assertEquals(Size.class, violation.getConstraintDescriptor().getAnnotation().annotationType());
        }
    }
}

Where my Customer looks like:

@Entity
public class Customer {
    @Id @GeneratedValue
    @NotNull
    private Long id;

    @NotNull
    @Size(min = 3, max = 80)
    private String name;

    private boolean archived;

    ...
}

But this was just an example to show a tiny part of the API.

In my opinion, you should actually handle the validation at the view level. Many presentation frameworks support Bean Validation: JSF 2.0, Wicket, Spring MVC...

See also

  • 6.3. Presentation layer validation
  • Spring MVC, Spring Bean Validation Framework and validating confirm password / confirm email fields.
  • Wicket JSR-303 Validators
  • TOTD #123: f:ajax, Bean Validation for JSF, CDI for JSF and JPA 2.0 Criteria API
like image 186
Pascal Thivent Avatar answered Oct 07 '22 21:10

Pascal Thivent