Friday 5 July 2019

JPA: @Column: Make the column as unique key


You can make the value of a column unique by applying unique constraint on it.

How to apply unique constraint on a column?
You can do this by using 'unique' attribute of @Column annotation.

@Entity(name = "MY_EMPLOYEE")
public class Employee {

         @Column(name = "EMPLOYEE_EMAIL", unique=true)
         private String email;
        
}

Find the below working application.

Employee.java
package com.sample.myApp.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity(name = "MY_EMPLOYEE")
public class Employee {

 @Id
 @GeneratedValue
 @Column(name = "EMPLOYEE_ID")
 private int id;

 @Column(name = "EMPLOYEE_FIRST_NAME")
 private String firstName;

 @Column(name = "EMPLOYEE_LAST_NAME")
 private String lastName;

 @Column(name = "EMPLOYEE_EMAIL", unique=true)
 private String email;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
 }

}


persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
 xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
 <persistence-unit name="myPersistenceUnit"
  transaction-type="RESOURCE_LOCAL">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

  <class>com.sample.myApp.entities.Employee</class>

  <properties>
   <property name="eclipselink.target-database" value="Derby" />
   <property name="javax.persistence.jdbc.driver"
    value="org.apache.derby.jdbc.ClientDriver" />
   <property name="javax.persistence.jdbc.url"
    value="jdbc:derby://localhost:1527/demoDatabase;create=true" />
   <property name="javax.persistence.jdbc.user" value="APP" />
   <property name="javax.persistence.jdbc.password" value="APP" />
   <property name="eclipselink.logging.level" value="INFO" />
   

   <property name="eclipselink.ddl-generation"
    value="drop-and-create-tables" />

   <property name="eclipselink.ddl-generation.output-mode"
    value="database" />
  </properties>

 </persistence-unit>
</persistence>


TestApp.java
package com.sample.myApp;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import com.sample.myApp.entities.Employee;

public class TestApp {

 private static void printEmployees(EntityManager em) {
  Query q = em.createQuery("SELECT e from MY_EMPLOYEE e WHERE e.firstName='Krishna' AND e.lastName='Gurram' ",
    Employee.class);
  List<Employee> emps = q.getResultList();
  for (Employee emp1 : emps) {
   System.out.println(emp1);
  }
 }

 private static void addEmployee(Employee emp, EntityManager em) {
  em.getTransaction().begin();
  em.persist(emp);
  em.getTransaction().commit();
 }

 public static void main(String args[]) {
  EntityManagerFactory emf = null;
  EntityManager em = null;

  try {
   emf = Persistence.createEntityManagerFactory("myPersistenceUnit");

   em = emf.createEntityManager();

   Employee emp = new Employee();
   emp.setFirstName("Krishna");
   emp.setLastName("Gurram");
   emp.setEmail("abc@abc.com");

   addEmployee(emp, em);
   printEmployees(em);

   emp = new Employee();
   emp.setFirstName("Siva");
   emp.setLastName("Ponnam");
   emp.setEmail("abc@abc.com");

   addEmployee(emp, em);
   printEmployees(em);
  } finally {
   if (em != null && em.isOpen()) {
    em.close();
   }

   if (emf != null && emf.isOpen()) {
    emf.close();
   }
  }

 }

}


When you ran TestApp.java, you will end up in DerbySQLIntegrityConstraintViolationException like below.

Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.1.v20171221-bd47e8f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL180627083739660' defined on 'MY_EMPLOYEE'.
Error Code: 20000
Call: INSERT INTO MY_EMPLOYEE (EMPLOYEE_ID, EMPLOYEE_EMAIL, EMPLOYEE_FIRST_NAME, EMPLOYEE_LAST_NAME) VALUES (?, ?, ?, ?)
 bind => [4 parameters bound]
Query: InsertObjectQuery(Employee [id=2, firstName=Siva, lastName=Ponnam, email=abc@abc.com])
 at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:159)
 at com.sample.myApp.TestApp.addEmployee(TestApp.java:26)
 at com.sample.myApp.TestApp.main(TestApp.java:51)


By default, index is created for the unique key constraint fields. You can confirm the same using DBVisualizer.

How to run above program without errors?
Change the email id of the second employee and rerun the program.

For example, I updated second employee details like below.
emp = new Employee();
emp.setFirstName("Siva");
emp.setLastName("Ponnam");
emp.setEmail("xyz@xyz.com");


TestApp.java
package com.sample.myApp;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import com.sample.myApp.entities.Employee;

public class TestApp {

 private static void printEmployees(EntityManager em) {
  System.out.println("**************************************");
  Query q = em.createQuery("SELECT e from MY_EMPLOYEE e", Employee.class);
  List<Employee> emps = q.getResultList();
  for (Employee emp1 : emps) {
   System.out.println(emp1);
  }
  System.out.println("**************************************\n");
 }

 private static void addEmployee(Employee emp, EntityManager em) {
  em.getTransaction().begin();
  em.persist(emp);
  em.getTransaction().commit();
 }

 public static void main(String args[]) {
  EntityManagerFactory emf = null;
  EntityManager em = null;

  try {
   emf = Persistence.createEntityManagerFactory("myPersistenceUnit");

   em = emf.createEntityManager();

   Employee emp = new Employee();
   emp.setFirstName("Krishna");
   emp.setLastName("Gurram");
   emp.setEmail("abc@abc.com");

   addEmployee(emp, em);
   printEmployees(em);

   emp = new Employee();
   emp.setFirstName("Siva");
   emp.setLastName("Ponnam");
   emp.setEmail("xyz@xyz.com");

   addEmployee(emp, em);
   printEmployees(em);
  } finally {
   if (em != null && em.isOpen()) {
    em.close();
   }

   if (emf != null && emf.isOpen()) {
    emf.close();
   }
  }

 }

}


Run TestApp.java, you can able to see below messages in the console.

[EL Info]: 2018-06-27 08:46:57.464--ServerSession(1978869058)--EclipseLink, version: Eclipse Persistence Services - 2.7.1.v20171221-bd47e8f
[EL Info]: connection: 2018-06-27 08:46:57.748--ServerSession(1978869058)--/file:/C:/Users/krishna/java9/jpaDemo/target/classes/_myPersistenceUnit login successful
**************************************
Employee [id=1, firstName=Krishna, lastName=Gurram, email=abc@abc.com]
**************************************

**************************************
Employee [id=1, firstName=Krishna, lastName=Gurram, email=abc@abc.com]
Employee [id=2, firstName=Siva, lastName=Ponnam, email=xyz@xyz.com]
**************************************

[EL Info]: connection: 2018-06-27 08:46:58.329--ServerSession(1978869058)--/file:/C:/Users/krishna/java9/jpaDemo/target/classes/_myPersistenceUnit logout successful



Previous                                                    Next                                                    Home

No comments:

Post a Comment