Suggested Pages

Saturday, June 30, 2012

JPA @ElementCollection

Suppose you have an entity bean called User and this entity has a lot of nicknames. You can make the following mapping:
User.java
 ...

@Entity
public class User {

   @Id
   private int userId;

   @Column
   private String name;

   @ElementCollection
   private Set nicknames;

   public User() {
      super();
      this.nicknames = new TreeSet();
   }
 ...

}


Database point of view

create table User (
        parentId integer not null,
        name varchar(255),
        primary key (parentId)
)
create table User_nicknames (
        User_parentId integer not null,
        nicknames varchar(255)
)

alter table User_nicknames 
        add constraint FKA44D16712C2B0AD9 
        foreign key (User_parentId) 
        references User

JPA Mapping : Embedded Object

In JPA/Hibernate an embedded object resolve this question: how can you design in your application domain an object that is part of an entity bean? An embedded object is an object that it's not linked to a concrete table. An embedded object can't be directly persisted or queried because it's not an entity. It can only be persisted as part of another entity and so it doesn't need an id
Declaring an embeddable object is very simple.

Step-1: Create a class and annotate it with @Embeddable annotation


Address.java
...
@Embeddable
public class Address {
 
 @Column
 private String street;
 
 @Column
 private String cap;
 
...
}


Step-2: Use @Embedded annotation inside your entity bean


User.java
...

@Entity
public class User implements Serializable{

 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int userId;

 @Column
 private String name;

 @Embedded
 private Address address;

...

}


Database Point of View

As i said before, you cannot persist or query an embedded object. Access to Address object requires access to User. If you try to persist Address object, you obtain the following error::
java.lang.IllegalArgumentException: Unknown entity: com.simonefolinojavablog.persistence.entity.Address.
If you use hibernate.hbm2ddl.auto property to automatically create tables in the DB, only one table is created.

   create table User (
        userId integer generated by default as identity (start with 1),
        cap varchar(255),
        street varchar(255),
        name varchar(255),
        primary key (userId)
    )
}

Override column names of an embedded object


In many cases an embedded object can be shared among entities but sometimes you need some variations to the field names of the embedded object.
Employee.java

...

@Entity
public class Employee {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int employeeId;

 @Column
 private String name;

 @Embedded
   @AttributeOverrides({
     @AttributeOverride(name="street", column=@Column(name="jobstreet"))
   })
 private Address address;

   ...
 
}
JPA/Hibernate creates the table below. As you can see the column name street is converted into a column name called jobstreet. database point of view

  create table Employee (
        employeeId integer generated by default as identity (start with 1),
        cap varchar(255),
        jobstreet varchar(255),
        name varchar(255),
        primary key (employeeId)
    )
}

JPA - EntityManager : Persist Entities Part II

Persist and CascadeType.Persist


In this previous post (JPA - EntityManager : Persist Entities Part I) we have seen three examples of using of persist method from the EntityManager.
We have seen that you cannot save an entity unless you have saved its dependency beans before. In that example you could not save Child entity before having saved Parent entity.
This behaviour can be changed using CascadeType.Persist on the @ManyToOne association. This attribute performs a cascade operation of persisting parent entity when you try to persist a child entity.

Parent.java
 ...
@Entity
public class Parent {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java

 ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne(cascade=CascadeType.PERSIST)
 private Parent parent;
 
 ...
}
Now when you make the following test, you won't encounter the same problem, so Child entity will be saved successfully.

GenericDAO.java
...

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Parent parent) {
  System.out.println("------------save(): start -------");
  entityManager.persist(parent);
  System.out.println("------------save(): end -------");
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Child child) {
  System.out.println("------------save(): start -------");
  entityManager.persist(child);
  System.out.println("------------save(): end -------");
 }
}


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveEntityWithTransientAssociation() {
  System.out.println("------------testSaveEntityWithTransientAssociation(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(child);
  System.out.println("------------testSaveEntityWithTransientAssociation(): end -------");
 }

}

Friday, June 29, 2012

Spring MVC @PathVariable - Tutorial

In this post we'll see an example of the using of @PathVariable in Spring MVC. Suppose this is your controller class.
AddressBookController.java
 ...

@Controller
@RequestMapping(value = "/dao")
public class AddressBookController {

 private static Logger logger = Logger
   .getLogger(AddressBookController.class);

 @Qualifier(value = "addressBookDAO")
 @Autowired
 private AddressBookDAO addressBookDAO;

   
 @RequestMapping(value = "/contact/add/{number}", method = RequestMethod.GET)
 public void add(@PathVariable(value = "number") String number ) {
  logger.debug("add contact()----start: " + number);
  Contact contact=new Contact();
  contact.setNumber(number);
  addressBookDAO.create(contact);
  logger.debug("add contact()----end");
 }
 
}
    
As you can see you @PathVariable is used to map a method parameter with a portion of the request URI. Now if you are interested into saving a contact with a given number telephone (for example 123456), you can make a request at the following URL: http://localhost:8083/<context>/<dispatcher-servlet>/dao/contact/add/123456 .
  • <context> : it is your application context path;
  • <dispatcher-servlet> : it is the value of url-pattern tag of the spring dispatcher-servlet used in your web.xml.

JPA - EntityManager : Persist Entities Part I

In this post we'll see the method persist of Entity Manager and we'll take a look at the most common problems, you can face.
Consider the following entity beans.
Parent.java

 ...
@Entity
public class Parent {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(cascade=CascadeType.PERSIST,mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java
 ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne
 private Parent parent;
 
 ...
}


GenericDAO.java

...

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Parent parent) {
  System.out.println("------------save(): start -------");
  entityManager.persist(parent);
  System.out.println("------------save(): end -------");
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Child child) {
  System.out.println("------------save(): start -------");
  entityManager.persist(child);
  System.out.println("------------save(): end -------");
 }
}

Save a transient entity



DAOTest.java
...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveTransientEntity() {
  System.out.println("------------testTransientEntity(): start -------");
  Child child=new Child();
  child.setChildId(1);
  child.setName("child1");
  genericDAO.save(child);
  System.out.println("------------testTransientEntity(): end -------");
 }

}

Persist method of Entity Manager can be applied to a transient entity. So this test method complete successfully.

Save a detached entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveDetachedObject() {
  System.out.println("------------testSaveDetachedObject(): start -------");
  Child child=new Child();
  child.setChildId(2);
  child.setName("child2");
  genericDAO.save(child);
  child.setName("childNew");
  genericDAO.save(child);
  System.out.println("------------testSaveDetachedObject(): end -------");
 }
 
}

Persist method of Entity Manager can't be applied to a detached entity. An error occurs: org.hibernate.PersistentObjectException: detached entity passed to persist: com.simonefolinojavablog.persistence.entity.Child ;
This happens because JPA/Hibernate distinguishes between transient entities and detached entities by the id. Because i used @GeneratedValue(strategy=GenerationType.IDENTITY) the database will create the id automatically when a row is created in the database.

Save an entity that has a dependency with another transient entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;

  
 @Test
 public void testSaveEntityWithTransientAssociation() {
  System.out.println("------------testSaveEntityWithTransientAssociation(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(child);
  System.out.println("------------testSaveEntityWithTransientAssociation(): end -------");
 }
 
}

}

Persist method of Entity Manager can't be be applied to a transient entity that has a dependency with another transient entity. An error occurs: object references an unsaved transient instance - save the transient instance before flushing: com.simonefolinojavablog.persistence.entity.Child.parent -> com.simonefolinojavablog.persistence.entity.Parent
This exception occurs because we have to persist the Parent entity before persisting Child entity. You cannot persist an entity that has references with a transient entity but you can if this entity is a detached entity.

Wednesday, June 27, 2012

JPA: ManyToOne Unidirectional Association

In this post we'll see an example of a unidirectional association ManyToOne.

Object point of view


Parent.java
...
@Entity
public class Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;

 @Column
 private String name;

        ...
}

Child.java
  ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;

 @ManyToOne
 private Parent parent;
       
        ...
}

Database Point of View


create table Child (
        childId integer generated by default as identity (start with 1),
        name varchar(255),
        parent_parentId integer,
        primary key (childId)
)

create table Parent (
        parentId integer generated by default as identity (start with 1),
        name varchar(255),
        primary key (parentId)
)

alter table Child 
        add constraint FK3E104FC9E7EF479 
        foreign key (parent_parentId) 
        references Parent

JPA: ManyToOne unidirectional association with JoinTable

In this post we'll see an example of a unidirectional ManyToOne with JoinTable relationship in JPA.

Object Point of View


Parent.java
 ...

@Entity
public class Parent {

 @Id
 private int parentId;

 @Column
 private String name;

 ...

}

Child.java
     ...

@Entity
public class Child {
 
 @Id
 private int childId;
 
 @Column
 private String name;

 @ManyToOne
 @JoinTable(name="Parent_Child", joinColumns=@JoinColumn(name="childId"), inverseJoinColumns=@JoinColumn(name="parentId"))
 private Parent parent;
 
 ... 

}


Database Point of View


[

create table Child (
        childId integer not null,
        name varchar(255),
        primary key (childId)
)

create table Parent (
        parentId integer not null,
        name varchar(255),
        primary key (parentId)
)

create table Parent_Child (
        parentId integer,
        childId integer not null,
        primary key (childId)
)

alter table Parent_Child 
        add constraint FK5AF11D47C916AC84 
        foreign key (parentId) 
        references Parent

alter table Parent_Child 
        add constraint FK5AF11D47ABE0291E 
        foreign key (childId) 
        references Child

As you can see in the above snippet of code Parent_Child is a table that has two foreign keys: the former with Parent table and the latter with Child table.
The Parent_Child table has also childId as primary key because a child cannot have different parents.

Tuesday, June 26, 2012

JPA: OneToMany Unidirectional Association

In this post we'll see an example of a unidirectional association OneToMany.

Object Point of View


Parent.java

@Entity
public class Parent {
 
 @Id
 private int parentId;
 
 @Column
 private String name;

 @OneToMany
 @JoinTable(name="Parent_Child", joinColumns=@JoinColumn(name="parentId"), inverseJoinColumns=@JoinColumn(name="childId"))
 private Set<Child> children;

 ...

}

Child.java

...

@Entity
public class Child {
 
 @Id
 private int childId;
 
 @Column
 private String name;
  
  ...
}



Database Point of View



create table Parent_Child (
        parentId integer not null,
        childId integer not null,
        primary key (parentId, childId),
        unique (childId)
)

create table Child (
        childId integer not null auto_increment,
        name varchar(255),
        primary key (childId)
)

create table Parent (
        parentId integer not null auto_increment,
        name varchar(255),
        primary key (parentId)
)

alter table Parent_Child 
        add index FK5AF11D47C916AC84 (parentId), 
        add constraint FK5AF11D47C916AC84 
        foreign key (parentId) 
        references Parent (parentId)

alter table Parent_Child 
        add index FK5AF11D47ABE0291E (childId), 
        add constraint FK5AF11D47ABE0291E 
        foreign key (childId) 
        references Child (childId)

As you can notice in the above snippet of code, we have three tables:
  • Child table;
  • Parent table;
  • Parent_Child: it has a primary key composed by parentId (the primary key of Parent table) and childId (the primary key of Child table).

Tuesday, June 19, 2012

Spring JdbcTemplate - Tutorial

In the following post i'll show an example of a way to use JdbcTemplate in Spring framework.
JdbcTemplate is a useful class that provides simple methods to retrieve, update and insert entities in the DB.
In the Javadoc it's written: JdbcTemplate semplifies the use of JDBC avoiding the common errors such as forgetting to always close the connection.
The method shown in this post has the following signature: List<T> query(String sql, RowMapper rowMapper). This method executes an SQL query and maps each row of the ResultSet to a Java object via a RowMapper.
RowMapper interface has a method: T mapRow(ResultSet resultSet, int arg1) throws SQLException that must be implemented. It has to map each row of data in the ResultSet into an Entity of the application domain.

As you can see in the following snippet, in the Spring context it's declared a bean called jdbcTemplate ( see ContactDAOTest-context.xml) and then i will use it in my test class (ContactDAOTest.java) via injection. You can notice that JdbcTemplate is a bean that only needs a Datasource to communicate with the database.

ContactDAOTest-context.xml


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
 xmlns:cxf="http://cxf.apache.org/core"
 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd   http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd    http://www.springframework.org/schema/jee  http://www.springframework.org/schema/jee/spring-jee-3.0.xsd    http://www.springframework.org/schema/tx   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 <!-- annotation support -->
 <context:annotation-config />

 <!-- support for transaction -->
 <tx:annotation-driven />

 <!-- scan package for @Repository annotations -->
 <context:component-scan base-package="com.simonefolinojavablog.persistence.dao" />


 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="dataSource" />
 </bean>


 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="com.p6spy.engine.spy.P6SpyDriver" />
  <property name="jdbcUrl" value="jdbc:hsqldb:mem:SN" />
  <property name="user" value="sa" />
  <property name="password" value="" />
 </bean>

 <bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceUnitName" value="persistenceUnitTest" />
  <property name="dataSource" ref="dataSource" />
  <property name="jpaVendorAdapter">
   <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="showSql" value="true" />
    <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
    <property name="generateDdl" value="true" />
   </bean>
  </property>
 </bean>

 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="entityManagerFactory" />
  <property name="dataSource" ref="dataSource" />
 </bean>

</beans>





The following class is a Test Class that makes use of JdbcTemplate.
I use query method of JdbcTemplate which has two parameters:
  • String: the sql statement to retrieve data from the DB;
  • RowMapper: an interface that we'll implement using an Anonymous Class.
In practice we'll make with RowMapper a sort of mapping between the ResultSet and the Contact entity.

ContactDAOTest.java

....

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.simonefolinojavablog.persistence.dao.ContactDAO;
import com.simonefolinojavablog.persistence.entity.Contact;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "ContactDAOTest-context.xml")
public class ContactDAOTest {

 @Autowired
 private JdbcTemplate jdbcTemplate;

 @Autowired
 private ContactDAO contactDAO;

 private static Contact contact1;
 
 private static Contact contact2;

 @BeforeClass
 public static void initContact() {
  System.out.println("------------initContact(): start -------");
  
  contact1 = new Contact();
  contact1.setNumber(4444);
  
  contact2 = new Contact();
  contact2.setNumber(5555);
  System.out.println("------------initContact(): end -------");
 }

 @Before
 public void insert(){
  
  contactDAO.save(contact1);
  contactDAO.save(contact2);
  
 }
 
 
 @Test
 public void testQuery() {
  
  List<Contact> contacts = jdbcTemplate.query("select * from Contacts", new RowMapper<Contact>() {
   
   public Contact mapRow(ResultSet resultSet, int arg1) throws SQLException {
    Contact contact=new Contact();
    contact.setNumber(resultSet.getInt("number"));
    return contact;
   }
  });
    
  System.out.println(contacts);

 }


}

Monday, June 18, 2012

JPA: GenericBean and Inheritance

In this post i'll show a way to outsource some entity properties. You can use inheritance to put in a superclass all the common properties shared among entities that extend it.
In the following snippet you can see GenericBean class that makes use of @MappedSuperclass annotation.
This annotation is used to tell JPA that the annotated class has a mapping to consider when you define entity that extends the superclass.

GenericBean.java

package com.simonefolinojavablog.persistence.entity;

...

@MappedSuperclass
public class GenericBean implements Serializable{

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;

 public int getId() {
  return id;
 }

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

Contact.java

package com.simonefolinojavablog.persistence.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "Contacts")
public class Contact extends GenericBean {

 
 private static final long serialVersionUID = -2436155670557423751L;
 
 @Column
 private int number;


 public int getNumber() {
  return number;
 }

 public void setNumber(int number) {
  this.number = number;
 }

 @Override
 public String toString() {
  return "Contact [number=" + number + "]";
 }

}


As you can see ContactDAO class uses GenericBean in its method signatures. In this way we can reduce the DAO class to write, because we only need a DAO class that persists, retrieves and edits GenericBean instead of particular entity bean.
ContactDAO.java

package com.simonefolinojavablog.persistence.dao;

...

@Repository(value = "ContactDAORequired")
public class ContactDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(GenericBean genericBean) {
  System.out.println("------------save(): start -------");
  entityManager.persist(genericBean);
  System.out.println("------------save(): end -------");
 }
}

Thursday, June 14, 2012

MySQL Datasource for JBoss 6.x

To configure a datasource for MySQL on JBOSS 6.x, you only need only three steps:

Step-1: Copy MySQL driver to server lib

Copy MySQL driver ( for example mysql-connector-java-5.1.19-bin.jar) into <JBoss-Home>/server/<jboss-server-configuration>/lib/

Step-2: Create mysql-ds.xml

Create a file mysql-ds.xml and put it into the directory <JBoss-Home>/server/<jboss-server-configuration>/deploy/.
mysql-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
   
    <jndi-name>myconnection</jndi-name>
    <connection-url>jdbc:mysql://localhost:3306/myschema</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>simone</user-name>
    <password>simone</password>

    <min-pool-size>2</min-pool-size>
    <max-pool-size>20</max-pool-size>
    <idle-timeout-minutes>5</idle-timeout-minutes>

    <exception-sorter-class-name>com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter</exception-sorter-class-name>
    <valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name>

  </local-tx-datasource>
</datasources>



Step-3:Use JNDI name in persistence.xml


Now you can use the JNDI name (java:/myconnection) configured in the previous step inside you persistence.xml.
persistence.xml

<persistence 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"
 version="2.0">
 <persistence-unit name="persistenceUnitTest">
  <jta-data-source>java:/myconnection</jta-data-source>
  <properties>
   <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
   <property name="hibernate.hbm2ddl.auto" value="create-drop" />
   <property name="hibernate.show_sql" value="true" />
   <property name="hibernate.format_sql" value="true" />
  </properties>
 </persistence-unit>
</persistence>

EntityManager (JPA) vs Session (Hibernate)

In this post i will show how to modify a detached object taking information from Hibernate and JPA reference site.

Session



GET

  • If it finds an object in the session with the same type and the same id in the session of passed object, it returns this persistent instance; otherwise it hits the database to retrieve the object;
  • If it can't find the object in session or in the database, it returns null.
You can use get() when you are not certain that the persistent object exists and when you want to test the return value to see if it’s null.

LOAD

  • If it finds an object in the session with the same type and the same id in the session of passed object, it returns this persistent instance; otherwise it doen't hit the database to retrieve the object, it returns a proxy of the given entity with the given identifier; to access the state of the proxy, you have to use accessor methods of the object that perform a query to the database. If the requested object does not exist an exception is thrown when the object is first accessed.
  • If it can't find the object in the session or in the database, an exception is thrown;
You can use load() when you are certain that the persistent object exists and when you are not interested into the persistence state of the entity. You can use the proxy just as reference to create relationships with other entities.

SAVE

  • If the entity has a generated identifier, this value is associated to the instance when save() is called;
  • If the entity has no identifier, the application-assigned key has to be set before call save() methods;
  • It inserts the entity into the session, but if an entity with the same identifier exists in the session an exception is thrown;
  • When the transaction commits, the entity will be written into the database, but if the primary key already present in the table, it cannot be inserted and an exception is thrown.
See save.

UPDATE

  • If the entity has no identifier (transient object), it will throw an exception;
  • If the entity has an identifier update() makes the entity becomes managed;
  • If there is a persistent instance with the same identifier, an exception is thrown.
See update.

SAVEOrUPDATE

  • It will INSERT or UPDATE depending on the value of the objects identifier.
  • If the entity has no identifier it will call save();
  • If the entity has an identifier it will call update().
  • If the identifier given to the entity is not in the database and an update() is performed, an exception will occurs because you are updating a record that doesn't yet exist.

See saveOrUpdate.

MERGE

  • If a persistence instance exists with the same identifier currently associated with the session, it copies the state of the detached object into the existing persistent instance. The given instance does not become associated with the session;
  • If there is no persistent instance currently associated with the session, try to load it from the database. Then it copies the state of the detached object into the returned persistent instance;
  • If the given instance is unsaved, save a copy of and return it as a newly persistent instance.


EntityManager



PERSIT

  • If the entity has a generated identifier, this value is associated to the instance when persist() is called;
  • If the entity has no identifier, the application-assigned key has to be set before call persist() methods;
  • It inserts the entity into the persistence context, but if an entity with the same identifier exists in the persistence context an exception is thrown;
  • When the transaction commits, the entity will be written into the database, but if the database already contains another entity of the same type with the same primary key, an exception is thrown.


FIND

  • It looks for a entity with the given id (primary key) into the persistence context;
    • If no entity is found in the persistence context, the entity is searched in the database;
  • If no entity is found in the database or in the persistence context, it returns null.
  • if entity is found in the database or in the persistence context, a managed entity returns.


GET_REFERENCE

  • It no entity is found in the persistence context with the given id (primary key), the entity is not searched in the database. A hollow object is initialized with the valid primary key and all its other persistent fields are uninitialized. The object content is retrieved from the database and the persistent fields are initialized, lazily, when the entity object is first accessed. If the requested object does not exist an EntityNotFoundException is thrown when the object is first accessed;
  • If an entity is found in the persistence context, a managed entity returns.


MERGE

  • If the passed object is a transient object it inserts the passed object into the database;
  • If the passed object is a detached object, it loads an entity from the persistence context. If an entity with the same identity (i.e. same type and primary key) is in persistence context, the content of the detached entity object is copied into the existing managed entity;
  • If no entity with the same identity is in the persistence context, a new managed entity object is constructed.
The detached object itself, however, remains unchanged and detached.

EJB : Transaction Rollback

As you know an enterprise java bean is transactional and you can declare a method to be transactional using specific annotations.
By default a transaction rolls back if an enterprise method throws an unchecked exception and a transaction commits if it throws a checked exception.
You can change this behaviour using @ApplicationException(rollback=true) at class level. Annotating a checked exeption with the above annotation, you can also perform a rollback in case of checked exception thrown by an enterprise method.
In the following snippets, you can see a Steteless Session bean that has three methods:
  • The method saveUncheckedException throws a Runtime exception so the transaction will roll back.
  • The method saveCheckedExceptionRollback throws a checked exception (CommitEception) so the transaction will commit.
  • The method saveCheckedExceptionCommit throws a checked exception (RollbackException) marked with @ApplicationException(rollback=true) so the transaction will roll back.

ServiceContactEJBRemote.java

package ejb.transaction.service;

import ejb.transaction.entity.Contact;
import ejb.transaction.exceptions.CommitException;
import ejb.transaction.exceptions.RollbackException;

@Remote
public interface ServiceContactEJBRemote {

 public void saveUncheckedException (Contact contact);
 
 public void saveCheckedExceptionCommit (Contact contact) throws CommitException;
 
 public void saveCheckedExceptionRollback (Contact contact) throws RollbackException;


ServiceContactEJB.java

package ejb.transaction.service;

...

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ServiceContactEJB implements ServiceContactEJBRemote {

 @PersistenceContext(unitName = "testUnit")
 private EntityManager entityManager;

 @TransactionAttribute(TransactionAttributeType.REQUIRED)
 public void saveUncheckedException(Contact contact) {
  entityManager.persist(contact);
  throw new RuntimeException();
 }

 @TransactionAttribute(TransactionAttributeType.REQUIRED)
 public void saveCheckedExceptionCommit(Contact contact)
   throws CommitException {
  entityManager.persist(contact);
  throw new CommitException();
 }

 @TransactionAttribute(TransactionAttributeType.REQUIRED)
 public void saveCheckedExceptionRollback(Contact contact)
   throws RollbackException {
  entityManager.persist(contact);
  throw new RollbackException();
 }
}


CommitException.java

package ejb.transaction.exceptions;

public class CommitException extends Exception {

 private static final long serialVersionUID = 1L;

 public CommitException() {
  super();
  
 }

 public CommitException(String message, Throwable cause) {
  super(message, cause);

 }

 public CommitException(String message) {
  super(message);
 
 }

 public CommitException(Throwable cause) {
  super(cause);
  
 }

}


RollbackException.java

package ejb.transaction.exceptions;

import javax.ejb.ApplicationException;

@ApplicationException(rollback=true)
public class RollbackException extends Exception{

 public RollbackException() {
  super();
 
 }

 public RollbackException(String message, Throwable cause) {
  super(message, cause);
  
 }

 public RollbackException(String message) {
  super(message);
 
 }

 public RollbackException(Throwable cause) {
  super(cause);
 
 }

 private static final long serialVersionUID = 1L;

}




Contact.java

package ejb.transaction.entity;

...

@Entity
@Table
public class Contact implements Serializable{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int id;
 
 @Column
 private String number;
 
 @Column
 private String type;

 public int getId() {
  return id;
 }

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

 public String getNumber() {
  return number;
 }

 public void setNumber(String number) {
  this.number = number;
 }

 public String getType() {
  return type;
 }

 public void setType(String type) {
  this.type = type;
 }
}

Wednesday, June 13, 2012

Remote Stateless Session Beans, Entity Beans and Serialization

Let's suppose you have an enterprise method of a Remote Stateless Session EJB like: public void save(Contact contact). Contact is an entity beans that must be a Serializable class.
Contact class needs to be serializable because a Remote Stateless Session EJB uses RMI protocol to communicate over network and RMI uses serialization to pass objects between JVMs.
If you don't make Contact a Serializable class, an exception may occur: java.io.NotSerializableException, when you invoke the enterprise method.
ServiceContactEJBRemote.java
@Remote
public interface ServiceContactEJBRemote {

 public void save (Contact contact);
 
}
ServiceContactEJB.java
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ServiceContactEJB implements ServiceContactEJBRemote {

 @PersistenceContext(unitName = "serviceContact")
 private EntityManager entityManager;

 @TransactionAttribute(TransactionAttributeType.REQUIRED)
 public void save(Contact contact) {
  entityManager.persist(contact);
 }

Contact.java

@Entity
@Table
public class Contact implements Serializable{

 @Id
 private int id;
 
 @Column
 private String number;
 
 @Column
 private String type;

        ...

Monday, June 11, 2012

Interprocess Communication (wait/notify)

Wait/Notify


In Java there is a mechanism of inter-process communication based on these java primitives:
  • wait(): tells the calling thread to release the monitor and go to sleep until another thread enters the same monitor and calls notify().
  • notify(): wakes up the first thread that called wait( ) on the same object.
  • notifyAll(): wakes up all the threads that called wait( ) on the same object. The highest priority thread will run first.
Wait and Signal mechanism is used to avoid the bad practice to use polling mechanism. We can distinguish two different types of waiting:
  • Active Waiting: a thread, waiting for a condition to verify, makes a loop to check that condition. This loop causes an unnecessary CPU cycle consuming
  • Passive Waiting: a thread, waiting for a condition to verify, goes to sleep until a thread that has the knowledge to check that condition, wakes up the sleeping thread.
In the following code you can see three classes:
  • Monitor class that acts as a monitor. It has a state to be synchronized represented by counter variable.
  • ThreadOne class subtracts the counter of the Monitor until 8 from 100. It calls subtract() method of the monitor, that uses a call to notifyAll() in order to wake up other threads waiting for the object lock;
  • ThreadTwo waits that the value of counter reaches 8. It calls check() method of the monitor, that uses wait() to release the lock and wait a thread to wake it up.
  • .

Monitor.java
package com.simonefolinoblogspot.waitsignal;

public class Monitor {

 private int counter = 100;

 public synchronized void subtract() throws InterruptedException {
  this.counter--;
  System.out.println(this.counter);
  this.notifyAll();
 }

 public synchronized void check() throws InterruptedException {
  while (counter > 8) {
   System.out.println("current thread must wait: "+ counter);
   this.wait();
  }
  System.out.println("counter: "+ counter);
 }

 public synchronized int getCounter() {
  return counter;
 }

 public synchronized void setCounter(int counter) {
  this.counter = counter;
 }

}


ThreadOne.java

package com.simonefolinoblogspot.waitsignal;

public class ThreadOne extends Thread {

 private Monitor monitor;

 public ThreadOne(Monitor monitor) {
  this.monitor = monitor;
 }

 public void run() {
  try {
   while (monitor.getCounter()>8){
      Thread.sleep(100); 
      this.monitor.subtract();
   }
   System.out.println("threadone completed");
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

}


ThreadTwo.java
package com.simonefolinoblogspot.waitsignal;

public class ThreadTwo extends Thread {

 private Monitor monitor;

 public ThreadTwo(Monitor monitor) {
  this.monitor = monitor;
 }

 public void run() {
  try {
   this.monitor.check();
   System.out.println("threadtwo completed");
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

}
As you can see wait() and notify() methods must be written into synchronized methods or into synchronized blocks. The method check() uses wait() inside a loop to check the sleeping condition after the thread has been waken. When a thread receives a notifyAll(), it can't acquire the lock until the subtract() method ends. But when subtrack() method ends, the awake thread will try to re-acquire the lock.

Sunday, June 10, 2012

JPA: Bidirectional Association

Bidirectional associations must be maintained consistent


Bidirectional associations must be maintained consistent in memory as possible, so when you navigate the associations of entities, you can access data perfectly consistent. Suppose you have a typical relationship between two entities as Person and Contact Probably you are interested into navigate from an instance of Contact to an instance of Person and the inverse. But this depends on your application domain and the use cases you have to implement.
Suppose these are your entities:
Person.java

@Entity
public class Person {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;
 
 
 @OneToMany(mappedBy="person",fetch=FetchType.EAGER)
 private List<Contact> contacts;
 
        ...
}
  
Contact.java
 
....
@Entity
public class Contact {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 
 @ManyToOne
 private Person person;
       
         ...
}

To maintain consistent in memory you usually do this:
 
       contact.setPerson(person);
       person.getContacts().add(contact);
       entityManager.persist(contact);
  
As you know, a bidirectional one-to-many relationship is designed with two tables:
  • Owner Side (Contact): the side of @ManyToOne annotation which is the owner of the relationship because it has a foreign key with Person table;
  • Inverse Side (Person): the side of @OneToMany annotation.

Just two considerations:
  • person.getContacts().add(contact); is used to maintain consistence in memory. Consider the situation in which a Person entity has a huge amount of Contact entity, this can lead to poor performance. So you must pay attention on your uses case and be sure you need to maintain this consistent. If you don't need it, you can avoid this operation.
  • contact.setPerson(person); is used to persist contact entity and write on Contact table the personID of person. Retrieving a person entity for only this reason, may be not enough to perform a retrieving from the database of person entity. In JPA you can use getReference method of EntityManager interface. This method doesn't perform a hit to the database but it just returns a proxy object having the id necessary to persist the contact entity
The previous code can be written at this way.
[

     Person readPerson = entityManager.getReference(Person.class, personid);
     contact.setPerson(readPerson);
     entityManager.persist(contact);

Only changes to the owner side will be reflected in the database


Another important thing to know is the following JPA/Hibernate behaviour:
  • If you modify the owner side, changes will be reflected in the database;
  • If you modify the inverse side, JPA/Hibernate doesn't care.
Now suppose you have the following bidirectional association between Parent and Child entities.
Parent.java

 ...
@Entity
public class Parent {
 
 @Id
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(cascade=CascadeType.PERSIST,mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java
 ...
@Entity
public class Child {
 
 @Id
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne
 private Parent parent;
 
 ...
}
And the following unit test class.
Child.java

....

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;

 
 @Test
 public void testSaveInverseSide() {
  System.out.println("------------testSaveInverseSide(): start -------");
  Child child=new Child();
  child.setChildId(1);
  child.setName("child1");
  Parent parent = new Parent();
  parent.setParentId(1);
  parent.setName("parent1");
  parent.getChildren().add(child); // OneToMany association
  genericDAO.save(child);
  genericDAO.save(parent);
  System.out.println("------------testSaveInverseSide(): end -------");
 }

 @Test
 public void testSaveManyToOne() {
  System.out.println("------------testSaveManyToOne(): start -------");
  Child child=new Child();
  child.setChildId(2);
  child.setName("child2");
  Parent parent = new Parent();
  parent.setParentId(2);
  parent.setName("parent2");
  child.setParent(parent); // ManyToOne association
  genericDAO.save(parent);
  genericDAO.save(child);
  System.out.println("------------testSaveManyToOne(): end -------");
 }
 
 
 public void testSaveBothSide() {
  System.out.println("------------testSaveBothSide(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  parent.getChildren().add(child);  // OneToMany association
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(parent);
  genericDAO.save(child);
  System.out.println("------------testSaveBothSide(): end -------");
 }
 
}
  • testSaveInverseSide(): perform the following SQL statement
    • insert into Child (name, parent_parentId, childId) values ('child1', '', 1)
    • insert into Parent (name, parentId) values ('parent1', 1)
  • testSaveManyToOne():
    • insert into Parent (name, parentId) values ('parent2', 2)
    • select parent_.parentId, parent_.name as name1_ from Parent parent_ where parent_.parentId=2
    • insert into Child (name, parent_parentId, childId) values ('child2', 2, 2)
  • testSaveBothSide():
    • insert into Parent (name, parentId) values ('parent3', 3)
    • select parent_.parentId, parent_.name as name1_ from Parent parent_ where parent_.parentId=3
    • insert into Child (name, parent_parentId, childId) values ('child3', 3, 3)

As you can see only the second and the third test method perform the right SQL insert into DB. I mean, only when the owner side (Child table) is changed, the foreign key column with the inverse side (Parent table) will be updated.

JPA/Hibernate:LazyInitializationException

This is one of the commonest exception that occurs in Hibernate or JPA. When you ask for a collection to an entity after the hibernate session has closed or after the object has been detached from the session, this exception may occur. As you know, you can declare an association between two entities: EAGER or LAZY. If you use LAZY when an object is retrieved from the DB, it's not initialized with the association marked as LAZY. The LAZY initialization avoids to perform a JOIN between the two entities, so only when you navigate an association marked LAZY inside a session, you hit the database for retrieving data. Suppose these are your entities:
Contact.java
 .....

@Entity
public class Contact {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;

 @Column
 private String number;

 @Column
 private String type;

 @ManyToOne
 private Person person;


 @Override
 public String toString() {
  return "Contact [id=" + id + ", number=" + number + ", type=" + type
    + ", person=" + person + "]";
 }


 public int getId() {
  return id;
 }


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


 public String getNumber() {
  return number;
 }


 public void setNumber(String number) {
  this.number = number;
 }


 public String getType() {
  return type;
 }


 public void setType(String type) {
  this.type = type;
 }


 public Person getPerson() {
  return person;
 }


 public void setPerson(Person person) {
  this.person = person;
 }

}


Person.java
  .....

@Entity
public class Person {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;
 
 @Column
 private String name;
 
 @Column
 private String surname;
 
 @OneToMany(mappedBy="person",fetch=FetchType.LAZY)
 private List<Contact> contacts;

 
 public int getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getSurname() {
  return surname;
 }

 public void setSurname(String surname) {
  this.surname = surname;
 }

 public List<Contact> getContacts() {
  return contacts;
 }

 public void setContacts(List<Contact> contacts) {
  this.contacts = contacts;
 }

 @Override
 public String toString() {
  return "Person [id=" + id + ", name=" + name + ", surname=" + surname+"]";
 }
}



Person entity has a LAZY association with Contact, so when you invoke find method of EntityManager as:
Person person=entityManager.find(Person.class, personID);
an entity is retrieved from the database but its collection of contacts is not initialized.
Suppose now you want to access on contacts inside the presentation layer.
contacts.jsp

 <c:forEach var="contact" items="${person.contacts}">
        <tr>
          <td>${contact.number}</td>
          <td>${contact.type}</td>
         <td>
          <table>
           <tbody>
             ...
            <tr>
             <td><a href="${updateContact}">update</a></td>
            </tr>
            <tr>
             <td><a href="${deleteContact}">delete</a></td>
            </tr>
           </tbody>

          </table>
         </td>
        </tr>
       </c:forEach>
As you can see, in this JSP you are asking all contacts of a certain person. But person entity is detached at this level, so an exception will occur: LazyInitializationException. To fetch data on an association marked LAZY, the entity must be inside the session

Wednesday, June 6, 2012

Spring: Required vs Requires_new (propagation attribute)

In this post we'll see the difference between REQUIRED and REQUIRES_NEW Spring: Required vs Requires_new.

REQUIRES_NEW

Suppose you have the following classes.

ContactDAO.java

@Repository
public class ContactDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;

 @Transactional(propagation = Propagation.REQUIRES_NEW)
 public void saveRequiresNew(Contact contact, int count) {
  System.out.println("saveRequiresNew--start");
  entityManager.persist(contact);
  if (count == 1) {
   throw new RuntimeException("RuntimeException");
  }
  System.out.println("saveRequiresNew--end");
 }


}

ContactService.java
....
@Service
public class ContactService {

 @Autowired
 private ContactDAO contactDAO;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequiresNew(Contact contactOuterTransaction,
   List contacts) {
  
  contactDAO.save(contactOuterTransaction);
  int i = 1;
  for (Contact contact : contacts) {
  
   try {
    contactDAO.saveRequiresNew(contact, i);
   } catch (RuntimeException e) {
    System.out.println(e.getMessage());
   }
   i++;
  }
 }
}

As you can see the method saveRequiresNew of ContactDAO has Propagation.REQUIRES_NEW as propagation attribute.
The outer transaction will be suspended and a new transaction starts for each call to this method. When the count variable gets the value 1, an exception is thrown. Because the exception is a runtime exception the transaction will be marked for rollback. The method saveRequiresNew of ContactService catches the exception ad prints the exception message. The exception doesn't reach the outer transaction boundary so it has no effect on the outer transaction completion. Each trasaction that has been opened inside saveRequiresNew of ContactDAO will be committed except the transaction that is marked for rollback, and when the outer transaction will be resumed, it will go to commit.

REQUIRED


 
  ContactDAO.java
 .....

@Repository
public class ContactDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequired(Contact contact, int count) {
  System.out.println("saveRequired--start");
  
  entityManager.persist(contact);
  if (count == 1) {
   throw new RuntimeException("RuntimeException");
  }
  System.out.println("saveRequired--end");
 }

}

ContactService.java
....
@Service
public class ContactService {

 @Autowired
 private ContactDAO contactDAO;

 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequired(Contact contactOuterTransaction,
   List contacts) {

  System.out.println(contactOuterTransaction);
  contactDAO.save(contactOuterTransaction);
  int i = 1;
  for (Contact contact : contacts) {
   System.out.println("contact:" + i);
   try {
    contactDAO.saveRequired(contact, i);
   } catch (RuntimeException e) {
    System.out.println(e.getMessage());
   }
   i++;
  }
 }
As you can see the method saveRequired of ContactDAO has Propagation.REQUIRED as propagation attribute. So the outer transaction is used in this method to perform operations with the Entity Manager.  When the count variable gets  the value 1, an exception is thrown. Because the exception is a runtime exception the transaction will go to rollback. The transaction used in the this method is the same of the outer method, so no data will be persisted. Indipendently if the outer method catches the exception, the transaction is already marked for rollback.

Optimistic Lock

Problem

A very common problem in a web application is when we have to change values in the DB after reading these values. Suppose the situation is: a user reads information on a flight and then he decides to book. A simple way to manage this situation can be the following:
  • Open transaction;
  • Read access to a record (information on a flight);
  • Write access to a record (book the flight);
  • Close transaction.
The main problem of managing this situation with one transaction is that you have to lock a record, causing performance problems for the application. In addition this solution does not take into account the waiting time of the user to book the flight. We need to use the isolation level REPEATABLE_READ in order to avoid the possible lost update anomalies.

Solution

A known solution to the above problem is to use an optimistic locking technique, that permits to set a lower isolation level such as READ_COMMITTED. The optimistic locking technique is the following:
  • Open transaction;
  • Read access to a record (information on a flight);
  • Close transaction;
  • Keep a copy of the record;
  • Open a transaction
  • Read the record to be modified and, if the contents of the record read coincides with the original copy previously saved, then you can update otherwise the user will be informed of the impossibility to update.
This approach is a good practice when the total number of database accesses is higher than the total number of anomalies.
The transaction is used only for the time necessary to update the record.
In the practice this technique can be performed using a match based on the version or the timestamp as described below.

Optimistic lock with timestamp

If the object is very complex, in order to decide if you have to update a record, to many fields must be checked. To overcome this drawback, it's a common practice insert an extra field in each record . This field can be a timestamp used to keep track of the last update for that record. If the read timestamp coincides with the original copy previously saved, you can proceed to update the row.

JPA optimistick lock with @Version

In JPA you can use @Version annotation to perform an optimistic strategy. You can apply @Version to a numeric or data type. MyBean.java
@Entity
public class MyBean implements Serializable{
 ...
  @Id
  @Column
  private int id;

  @Version
  @Column
  private int version;

}
Suppose that two transactions will retrieve an entity with the same internal state from the DB and try to update it. The first transaction that is going to commit, will make a match between the version id of the database entity and the version id of the modified entity.The version id wil be the same so the transaction will commit and update the version id successfully.
The second transaction will find the version id with an higher value in the DB, so an OptimistickLockException will occur.
I'll speak about this exception in a next post.

Tuesday, June 5, 2012

J2EE Transaction Propagation vs Spring Transaction Propagation

J2EE Transaction Propagation

In a J2EE environment you can give information to the container to manage transactions. There are six transaction attribute to know:
  • Required
  • RequiresNew
  • Mandatory
  • Supports
  • NotSupported
  • Never

Nested or multiple transactions are not allowed within a method. The J2EE platform supports only flat transactions.

Required

In a CMT environment, Required is the implicit transaction attribute.
  • If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction;
  • If the client is not associated with a transaction, the container starts a new transaction before running the method.


RequiresNew

  • If the client is running within a JTA transaction and invokes the enterprise bean’s method, the container takes the following steps:
    • Suspends the client’s transaction;
    • Starts a new transaction;
    • Delegates the call to the method;
    • When the method and the transaction complete, the container resumes the suspended transaction
  • If the client is not associated with a transaction, the container starts a new JTA transaction before running the method.

You should use the RequiresNew attribute when you want to ensure that the method always runs within a new transaction. Suppose the original Required transaction rolls back, the RequiresNew transaction will still be persited.

Mandatory

  • If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction;
  • If the client is not associated with a transaction, the container throws the TransactionRequiredException.
Use the Mandatory attribute if the enterprise bean’s method must use the transaction of the client.

Supports

  • If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction;
  • If the client is not associated with a transaction, the container does not start a new transaction before running the method.


NotSupported

  • If the client is running within a transaction and invokes the enterprise bean’s method, the container suspends the client’s transaction before invoking the method. After the method has completed, the container resumes the client’s transaction;
  • If the client is not associated with a transaction, the container does not start a new transaction before running the method.
Use the NotSupported attribute for methods that don’t need transactions. Because transactions involve overhead, this attribute may improve performance.

Never

  • If the client is running within a transaction and invokes the enterprise bean’s method, the container throws a RemoteException.
  • If the client is not associated with a transaction, the container does not start a new transaction before running the method.


Spring Transaction Propagation

  • Required
  • Requires_New
  • Mandatory
  • Supports
  • NotSupported
  • Never
  • Nested

Required

If a transaction exists it's used otherwise a new one i started

Requires_New

Active transactions are suspended and a new one started. If none transaction exists a new transaction is started. This new transaction is independent from the suspended transaction, it will be committed or rolled back independent from the outer transaction. The new transaction has its own isolation scope,and locks. The outer transaction is suspended at the beginning of the inner one, and will be resumed once the inner one has completed.

Mandatory

If there's no active transaction a RemoteException is thrown.

Supports

If a transaction exists it's used otherwise execution is done not transactional.

NotSupports

If a transaction exists, it will suspend any active transaction.. Does not support execution within an active transaction.

Never

If a transaction exists a RemoteException is thrown. Otherwise execution is non transactional.

Nested

It starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. Íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of the outer transaction, so it will only be committed at the end of of the outer transaction.
Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction.
(Juergen Hoeller)

It can only be used with a DataSourceTransactionManager and a JDBC3 driver. It uses save points in order to be able to rollback some part of a transaction.

Sunday, June 3, 2012

Spring Transaction Rollback

Spring Framework has the following default configuration about transactions:
  • Marks a transaction for rollback when a Unchecked Exceptions is thrown;
  • Doesn't mark a transaction for rollback when a Checked Exceptions is thrown.

PersistenceDAOException.java
package com.simonefolinojavablog.persistence.dao.exception;

public class PersistenceDAOException extends Exception{

 public PersistenceDAOException() {
  super();
 }
}

Transaction rolls back when Unchecked Exceptions is thrown
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Contact contact) throws PersistenceDAOException {
  entityManager.persist(contact);
  throw new RuntimeException();
 }

The above transaction rolls back because it throws an unchecked exception.

Transaction commits when Checked Exceptions is thrown
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Contact contact) throws PersistenceDAOException {
  entityManager.persist(contact);
  throw new PersistenceDAOException();
 }
The above transaction commits because it throws a checked exception.

Transaction rolls back when Checked Exceptions is thrown and rollbackForClassName is used
[
 @Transactional(rollbackForClassName={"PersistenceDAOException"} ,
                       propagation = Propagation.REQUIRED)
 public void save(Contact contact) throws PersistenceDAOException {
  entityManager.persist(contact);
  throw new PersistenceDAOException();

 }
The above transaction rolls back because, i have declared PersistenceDAOException in the attribute rollbackForClassName.
Alternatively we can use the AOP confuguration to achieve the same goal.

 
<aop:aspectj-autoproxy />
    
     
<aop:config>
 <aop:pointcut id="rollbackService" expression="execution(public * save(..))" />
 <aop:advisor pointcut-ref="rollbackService" advice-ref="txAdvice" />
</aop:config>

 
<tx:advice id="txAdvice" transaction-manager="transactionManager">
 <tx:attributes>
  <tx:method name="save" rollback-for="PersistenceDAOException" />
 </tx:attributes>
</tx:advice>

Suggested Pages