Saturday, 23 March 2013

JPA 2.0 + Hibernate: OrphanRemoval & CascadeType.REMOVE

Here I am writing to cover up the difference between OrphanRemoval=true and CascadeType.REMOVE in JPA2.0 with hibernate.

Let say there is one to many relationship between User and Address and that can be defined in JPA as below:
public class User{     
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
        mappedBy = "user")
    public Set getAddresses() {
       return this.addresses;
    }
}
public class Address{
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="userid") 
    public User getUser() {
       return this.user;
    }
} 
You can have more detail in this post about above entities.

If I want to fetch the user entity and corresponding addresses, I can use below piece of code:
EntityManagerFactory emf 
  = Persistence.createEntityManagerFactory("StateCityService");
EntityManager entityManager= emf.createEntityManager();  
//fetching user entity based on id 
User user = entityManager.find(User.class, userId);  
// Lazy loading of addresses 
Set addresses = user.getAddresses(); 
Now if I change any state of user or address entity and execute merge operation on user entity, then corresponding User's and Address table's column value will be updated.
entityManager.merge(user);
That means, If I remove couple of address items from the set which user entity holds and perform merge operation on user entity, corresponding address rows (which have been removed from the collection defined in user entity) should be deleted based on CascadeType.ALL(add/remove/update). What do you think? You might answer yes. Even I think so.

But not really, CascadeType.REMOVE dose not help you in this scenario.

Achieving same thing in my project I invested couple of ours and found the solution. I had to use OrphanRemoval=true with one to many relationship to achieve this.
public class User{     
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
       orphanRemoval=true, mappedBy = "user")
public Set getAddresses() { return this.addresses; } }
'OrphanRemoval=true' Vs 'CascadeType.REMOVE'

The difference between the two settings is in the response to removing child objects from the collection pointed by parent entity.

If orphanRemoval=true is specified the removed address instance is automatically removed. If only cascade=CascadeType.REMOVE is specified no automatic action is taken since removing a relationship is not a remove operation. 

Where 'OrphanRemoval=true' and 'CascadeType.REMOVE' are identical ?

When an User entity object is removed the remove operation is cascaded to the referenced Address entity object. In this case, orphanRemoval=true and cascade=CascadeType.REMOVE are identical.

Use this link to have more detail.

Sunday, 17 March 2013

Spring MVC Portlet in Liferay

Liferay is one of the portal frameworks based on java. You can create portlets in Liferay using Spring MVC framework. This post may give you the answer of your one question "How to create a portlet in Liferay using Spring MVC ? ".  You can setup Liferay from here

Let's think about a user interface where search contents can be added into a search repository. Let's play with Liferay and Spring MVC Portlet to provide this user interface and feature. We can have a portlet named 'Add Search Content Portlet' as a user interface to add the search contents into a search repository.

Add Search Content Portlet: This portlet can have three fields to add the search contents: ID, Title and Description. If you see in below screen shots, I have added three hotel names as search content in terms of ID (hotel id), Title (hotel name) and Description (about hotel). 


Steps for Portlet Implementation  

To implement a portlet in Liferay using Spring MVC you need to follow below steps. Source code can be referred from document. 

1. Configuring Spring context file, this is a core configuration in applicationContext.xml file where you need to define the   message bundle, view resolver, portlet resolver etc.  [refer (a) in document]

2. Adding configuration in portlet.xml, liferay-display.xml and liferay-portlet.xml. These are the liferay specific configuration files, where you need to define the portlet name and   display name, portlet specific configuration file like addSearchContent.xml etc. [refer (b), (c) and (d) in document]

3. Configuring portlet specific configuration file like addSearchContent.xml, where you define the controller bean which serves the request for this  portlet. [refer (e) in document]

4. Creating java value objects, these objects are used to map JSP filed values into java object. [refer (f) in document]

5. Defining the controller class, this is a controller class where actual request is served for this portlet. [refer (g) in document]

6. Creating JSP, where portlet UI is defined. [refer (h) in document]

After creating all above source files you can build your application and then deploy on application server. Access your Liferay server, add a test page and add your new portlet on test page. You can refer this link to add new portlet into your page.

                                  
Refer below links for more detail:


JPA 2.0 Criteria Query + Hibernate



Criteria Query has been introduced in JPA 2.0. With the help of criteria queries you can write your queries in a type-safe way. Before criteria queries, developers had to write queries through the construction of object-based query definitions. There might be chances of incorrect syntax while building the queries. The criteria query API provides feature to create structured and nested queries with compile time safety. Getting into more theory about criteria query may not be a good idea as there are plethora of pages can be found on net for same. Let's have a simple example to understand query using criteria query. In this post, I used hibernate as vendor with JPA 2.0 to show the example of Criteria Query.

Before going into deep about criteria query, let's think about database tables and corresponding java classes which can be represented as entities:           

Database Tables:

For example we have below two database tables:
    1.   State [stateId, stateName]
    2.   City [cityId, stateId(FK#), CityName]
We want to fetch list of cities for a particular state where city name should be started from 'M' and city list should be in ascending order. If we think about simple native SQL, it would be like below:

Select * from City c, State s where c.stateId = s.stateId and c.stateId = ? and c.cityName like "M%" order by c.cityName

JPA Entities:

Below are the two java classes configured as JPA entities to represent state and city tables. These can be generated using reverse engineering tool as well.

Java entity for STATE table
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.Date;
import java.util.Set;
import javax.persistence.SequenceGenerator;

@Entity
@Table(name="STATE")
@SequenceGenerator(sequenceName="STATE_SEQ",name="STATE_SEQ_GEN")
public class State {
    private Long stateId;
    private String stateName;
    private Set<CityVO> citySet;
    @Id
    @Column(name="stateId")
    @GeneratedValue(generator="STATE_SEQ_GEN",strategy=GenerationType.SEQUENCE)
    public Long getStateId;() {
       return stateId;
    }
    public void setId(long stateId) {
        stateId = stateId;
    }

   @Column(name="stateName")
    public String getStateName() {
        return stateName;
    }
    public void setStateName(String stateName) {
        this.stateName = stateName;
    }
    public void setCitySet(Set<CityVO> citySet)
        this.citySet= citySet;
    }

    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="state")
    public Set getCitySet() {
        return citySet;
    }
}

Java entity for CITY table
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="CITY")
@SequenceGenerator(sequenceName="CITY_SEQ",name="CITY_SEQ_GEN")
public class City {
    private Long cityId;
    private String cityName;
    private State state;

    public void setId(long cityId) {
        this.cityId = cityId;
    }
 @Id
 @Column(name="CityId")
 @GeneratedValue(generator="CITY_SEQ_GEN",strategy=GenerationType.SEQUENCE)
    public Long getCityId() {
        return cityId;
    }
    @Column(name="CityName")
    public void setContent(String cityName) {
        this.cityName = cityName;
    }
    public String getCityName() {
        return cityName;
    }
    public void setState(State state) {
        this.state = state;
    }
   @ManyToOne(fetch =  FetchType.LAZY)
   @JoinColumn(name = "STATEID", nullable = false)
    public state getState() {
        return state;
    }
}

Value Objects (POJO):

Below are the two value objects. With the help of criteria query you can directly map your value objects from result data. You don't need to write the code to copy the result data from entity classes to your values objects. This is really an exciting feature in criteria query.

public class StateVO {
    private Long stateId;
    private String stateName;
    private Set<CityVO> cityVOSet;
   // All getter setters
 }
public class CityVO {
    private Long cityId;
    private String cityName;
    private StateVO stateVO;
    public CityVO( Long cityId, String cityName){
                  this.cityId=cicityId;
                  this.cityName=cityName;
    }
    // All getter setters
}

DAO Implementation:

Now this is the time where we can use criteria query to fetch the data. We will expose a method which will take input argument as StateVO and will return list of CityVOs.  
     
       import javax.persistence.EntityManager;
       import javax.persistence.EntityManagerFactory;
       import javax.persistence.Persistence;
       public class StateCityDAOImpl{
       
       public List<CityVO> getCityList(StateVO searchStateVO)  {
         // Get the entity manager instance
         EntityManagerFactory emf = Persistence.createEntityManagerFactory("StateCityService");
         EntityManager entityManager= emf.createEntityManager();
     
         // Get the criteria builder instance from entity manager
        final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
       
       // Create criteria query and pass the value object which needs to be populated as result
        final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(CityVO.class);
     
        // Tell to criteria query which tables/entities you want to fetch
        // To join the City and State tables, we need to write below code
        final Root stateRoot = criteriaQuery.from(State.class);
        final Root cityRoot = criteriaQuery.from(City.class);
   
       // Time to define where clause in terms of Predicates
        // This list will contain all Predicates (where clauses)
        List criteriaList = new ArrayList();
    
       // Note: Ensure that whatever string you are passing in root variables
        // It should be matched with variables' name in entity classes
     
        // [1] where condition: State.StateId = City.StateId
        Predicate predicate1 = criteriaBuilder.equal(
                cityRoot. get("state"). get("stateId"),
                stateRoot.  get("stateId"));
        criteriaList.add(predicate1);

        // [2] where condition: City.StateId = ?
        if (searchStateVO.getStateId() != null) {
           Predicate predicate2= criteriaBuilder.equal(
                    cityRoot. get("state"). get("stateId"),
                    searchStateVO.getStateId());
            criteriaList.add(predicate2);
        }

        // [3] where condition: City.cityName like 'M%'
        Predicate predicate3
                  = criteriaBuilder.like(criteriaBuilder.upper(cityRoot. get("cityName")),
                      "M%");
            criteriaList.add(predicate3);  
     
        // This statement maps your CityVO with result data
        // You have to have a custom constructor in CityVO  (see above) to populate the result data   
        criteriaQuery.select(criteriaBuilder.construct(CityVO.class, cityRoot. get("cityId"),
                cityRoot. get("cityName")));
 
        // Pass the criteria list to the where method of criteria query
        criteriaQuery.where(criteriaBuilder.and(criteriaList.toArray(new Predicate[0])));

        // Order by clause based on city names
        criteriaQuery.orderBy(criteriaBuilder.asc(cityRoot. get("cityName")));

        // Here entity manager will create actual SQL query out of criteria query
        final TypedQuery query = entityManager.createQuery(criteriaQuery);
      
        // This code can be used to define the row range to fetch the result
        /* if (CitySize != 0) {
            query.setFirstResult(startIndex); // starting row index
            query.setMaxResults(endIndex); //  end row index
       }*/
        return query.getResultList();
  }

Now we have CityVO list as answer in your hand. We can access the corresponding city name based on our aforementioned requirement.

Though, writing queries using criteria query may be little bit clumsy but once you get handy, you will enjoy the Criteria Query.