Friday, August 30, 2013

Compound Primary Keys in Hibernate using Annotations

most of the cases, identifier (primary key) of the entity will be a single attribute. but there will be some cases where the primary key of the entity will be comprised by several attributes. In other words, primary key will consist of more than one column. if the primary key consist of more than one attribute/column, we called it as composite primary key or compound primary key.

  In hibernate, there are three ways that can be used to create compound primary key in a entity class using annotations. In all of these three scenarios, it will be required to create a separate class for the compound primary key.

1. Compound primary key with  @Embeddable annotation
 mark the compound primary key (PK) class with @Embeddable annotation and  add the instance of the PK class to the entity class as a normal property. then mark it with @Id annotation as usual.


2. Compound Primary key with @EmbeddableId annotation
 create the compound PK class as  POJO (Plain Old Java Object) and add it as a normal property for the Entity class. then mark that instance with @EmbeddableId annotation.


3. Compound Primary key with @IdClass annotation
    declare the compound primary key class with @IdClass annotation and add the all primary key properties of that class to the entity class as normal properties. then mark all the added primary key properties with @Id annotation.



Hope this will be helpful for you!

Cheers
Chathuranga Tennakoon
www.chathurangaonline.com

Tuesday, August 20, 2013

Hibernate 4 - One to Many mapping with Annotations (LAZY loading example)

 the technologies i ma using for this example.

Hibernate 4
testNG for TDD
MySQL
Maven

In this example, we are going to use our Lecturer and Course example again the entity relationship will be decided based on the following assumption.

Assumption:
 Lecturer can teach many number of courses.

Therefore the relationship between two entities can be described as follows.

  •  relationship from Lecturer to Course is One-To-Many (lecturer can teach many number of courses) 
  •  relationship from Course to Lecturer is Many-To-One (many courses will be taught by one lecturer)
Refer the below example.

Lecturer.java
package com.chathurangaonline.examples.model;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

@Entity
@Table(name = "Lecturer")
public class Lecturer implements Serializable{

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

    @OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,mappedBy = "lecturer")
    private List courseList;

    public Long getId() {
        return id;
    }

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

    public List getCourseList() {
        return courseList;
    }

    public void setCourseList(List courseList) {
        this.courseList = courseList;
    }
}





Course.java
package com.chathurangaonline.examples.model;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "Course")
public class Course implements Serializable{

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

    @Column(name = "course_name")
    private String courseName;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "lecturer_id")
    private Lecturer lecturer;

    public Long getId() {
        return id;
    }

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

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public Lecturer getLecturer() {
        return lecturer;
    }

    public void setLecturer(Lecturer lecturer) {
        this.lecturer = lecturer;
    }
}




i have used the following code to check the mapping relationship  and the lazy loading.



    @Test
    public void testSave() throws Exception {

        //saving the lecturer
        Lecturer lecturer = new Lecturer();
        lecturerDao.save(lecturer);
        Assert.assertNotNull(lecturer.getId());

        //saving the course
        Course course = new Course();
        course.setCourseName("Java");
        course.setLecturer(lecturer);
        courseDao.save(course);
        Assert.assertNotNull(course.getId());

        System.out.println(" retrieving the lecturer record with id ["+lecturer.getId()+"]");
        Lecturer  lecturer2  = lecturerDao.findById(lecturer.getId());
        System.out.println("lecturer found with id ["+lecturer2.getId()+"] retrieved");
        System.out.println("course retrieving .......");
        List  courseList1 = lecturer2.getCourseList();
        System.out.println(" course list retrieved ["+courseList1.size()+"]");
    }


when i run the above code, i got the following output and seems to be that the lazy loading is also working fine.



you can get the example source code from following gitHub repository.
Get SourceCode from GitHub


Hope this will be helpful for you!

Cheers
Chathuranga Tennakoon
chathuranga.t@gmail.com
www.chathurangaonline.com


Monday, August 12, 2013

Lazy loading not wotking with hibernate OneToOne mapping

in my experience, i have encountered an issue that the hibernate lazy loading is not working when we map the relationship between two entities  using OneToOne annotations.see the following examples.

Lecturer.java

package com.chathurangaonline.examples.model;



import javax.persistence.*;

import java.io.Serializable;



@Entity
@Table(name = "Lecturer")
public class Lecturer implements Serializable{

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


    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name = "course_id")
    private Course course;


    public Long getId() {
        return id;
    }


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


    public Course getCourse() {
        return course;
    }


    public void setCourse(Course course) {
        this.course = course;
    }
}





Course.java

package com.chathurangaonline.examples.model;


import javax.persistence.*;
import java.io.Serializable;


@Entity
@Table(name = "Course")
public class Course implements Serializable{

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


    @Column(name = "course_name")
    private String courseName;


    @OneToOne(fetch = FetchType.LAZY,mappedBy = "course")
    private Lecturer lecturer;


    public Long getId() {
        return id;
    }


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


    public String getCourseName() {
        return courseName;
    }


    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }


    public Lecturer getLecturer() {
        return lecturer;
    }


    public void setLecturer(Lecturer lecturer) {
        this.lecturer = lecturer;
    }
}



you will notice that the mapping from the lecturer to course is One-To-One and the fetch type is LAZY. Since the fetch type is LAZY, the associated course object should not be loaded when the lecturer object is loaded. the associated course object should be loaded only when the user request it. that is the behavior of the lazy fetch mode.

    but in this example, you will notice that course object is loaded (EAGER resolved) when the time that the lecturer object is loaded regardless of the LAZY fetch type. it always eagerly resolve the associated entities even if it is declared as LAZY fetch. . please refer the below screenshot.


you will see that when retrieving the Lecturer object with given id, it generates and issue a SQL query to retrieve data from the database. when the lecturer object is retrieved, it loads and populates the associated course object also. that is why when we request the course object and its attributes, it directly give the values of the attributes without issuing another SQL query. the reason for this EAGER behavior can be described as follows.


    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name = "course_id")
    private Course course;

you will notice that the OneToOne relationship is not mandatory and it is optional.(by default, the optional=true). since the relationship is optional, hibernate(ORM framework) does not know whether the given lecturer teach a course or not without issuing an another query. therefore hibernate cannot populate the course reference with a proxy, because it does not know whether a course exists for that lecturer.  On the other hand, it cannot populate the course attribute with null because, there may be lecturers who teach courses. therefore hibernate performs the EAGER loading regardless of the LAZY fetch mode if the relationship is OneToOne and it is optional.

to overcome to above issue and make the LAZY loading working, you need to make the relationship as mandatory. In oder to do that, set the optional=false.

   @OneToOne(fetch = FetchType.LAZY,
                        cascade = CascadeType.ALL,
                        optional = false)
   @JoinColumn(name = "course_id")
   private Course course;



then the lazy loading should works as usual.
refer the following screenshot and identify how the lazy loading works. refer the below screenshot.


you will see that when retrieving the associated course instance from the lecturer instance, it generates another SQL queries to retrieve the course details associated. this is because the Fetch type of the relationship is LAZY.


references :
http://stackoverflow.com/questions/17987638/hibernate-one-to-one-lazy-loading-optional-false


Hope this will be helpful for you!

Thanks
Chathuranga Tennakoon
chathuranga.t@gmail.com
www.chathurangaonline.com







Tuesday, August 6, 2013

XML based mapping VS Annotation based mapping in hibernate

There are two ways that we can perform entity mapping in hibernate.
1. XML based mapping
2. Annotation based mapping.

the intention of this article is to select the appropriate mapping option for your project. by the way, i always prefer the annotation based mapping for my projects because of the following reasons.

  • i personally hate a load of XML mapping files and it adds unnecessary complexity for the project. 
  • it degrade the readability and understandability of the code because your POJO (Plain Old Java Objects) is independent from the relevant XML mapping files. therefore you cannot understand the database constraints, associations and mapping relationships between entities just looking at only the POJOs. you need an additional effort to read the XML mapping files and POJOs simultaneously to get an understanding of how entity mapping has been done.

 i personally prefer the annotation based mapping because of the following reasons.

  •  it is very simple to perform entity mapping with annotations and i don't have to maintain separate XML configuration files. 
  • In Annotation mapping,the entity relationships, mappings and other DB constraints are also defined in the POJO along with the relevant attribute. therefore it improves the understandability and the readability of the code.

The decision of selecting the appropriate mapping option (either Annotation based or XML based) for your project should be done wisely.

when to use XML based mapping


it is safer to use XML based mapping to integrate/use the hibernate for a project that is already developed. since you are using XML based mapping, you do not have to touch or modify the POJO classes that are already developed and stable. if you are confident enough to modify the POJOs, then you may use annotation based mapping.(But not recommended)

Another scenario where we can use the XML based mapping is that, we are getting a request  to integrate/use the hibernate for a project that is already developed. but the problem is we do not have the source code of the POJO classes. at that time, we cannot use the annotation to map the entities because, we do not have the source code of POJOs. in such case, we have to use the XML based mapping.


when to use the Annotation based mapping

XML based mapping is a proprietary format of Hibernate ORM framework.
if you intend to expose your applications to other JPA2 compliant other ORM frameworks, you must use the Annotation based mapping. but keep it in mid that there are two types of annotations.
  •  Annotations in the javax.persistance package
In oder to comply, your application with the JPA 2 specification standards, you must use the annotations provided in this package.
  •  Annotations in the org.hibernate package
Annotations provided in this package also specific to the hibernate. In otherwords, all these annotations are owned and governed by the hibernate. therefore  if you have used this annotations,your application will not comply with JPA 2. therefore the application will not work with other ORM frameworks compliant with JPA2. therefore using these annotations will produce the same effect as XML based mapping. only difference between the XML and Annotation (org.hibernate package) based mapping is that it is XML and this is annotations.



Hope this will be helpful for you!
Cheers
Chathuranga Tennakoon
www.chathurangaonline.com

Friday, August 2, 2013

Hibernate One To One Bidirectional Mapping with Annotations

Assumption : Lecturer can teach only one Course and the given Course can be taught only by one lecturer.  therefore we will use One To One mapping here

Lecturer.java


package com.chathurangaonline.examples.model;

import javax.persistence.*;

@Entity
@Table(name = "Lecturer")
public class Lecturer {

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

    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL,optional=false)
    @JoinColumn(name = "course_id")
    private Course course;

    public Long getId() {
        return id;
    }

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

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

}




Course.java

package com.chathurangaonline.examples.model;

import javax.persistence.*;

@Entity
@Table(name = "Course")
public class Course {

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

    @Column(name = "course_name")
    private String courseName;

    @OneToOne(mappedBy = "course",fetch = FetchType.LAZY)
    private Lecturer lecturer;

    public Long getId() {
        return id;
    }

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

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public Lecturer getLecturer() {
        return lecturer;
    }

    public void setLecturer(Lecturer lecturer) {
        this.lecturer = lecturer;
    }
}



you will see that there is a mapping relationship between Lecturer and Course entities. this relationship is  bidirectional mapping relationship because each entity contain the reference for other entity. in bidirectional relationship, one entity will manage and own the foreign key relationship. it is the entity that holds the forien key too.

what is mappedBy atrribute?

as i have described above, in bidirectional relationship one entity will own  and manage the foreign key relationship. the other entity (which does not manage the foreign key) uses the mappedBy attribute to tell that who is the owner of the foreign key relationship.

    @OneToOne(mappedBy = "course",fetch = FetchType.LAZY)
    private Lecturer lecturer;

 in this example, mappedBy attributes says that "Hey, i am not the owner of the foreign key and i do not manage it.  it is owned and managed by the course attribute belongs to the Lecturer entity.


Hope this will helpful for you.

Cheers
Chathuranga Tennakoon
www.chathurangaonline.com

Thursday, August 1, 2013

Android Development- Setting Up development environment and Hello World Application

I have decided to start new post series on Android Application development. Before starting the android application development, we need to set up our development environment.

Here I am using the Eclipse IDE for the android application development. In order to set up the android development environment in the existing Eclipse IDE, it is required to install few software tools (Android SDK, ADT plugin etc). I feel like it will take some time and effort to install that in my existing Eclipse IDE. Therefore I downloaded the ADT bundle and extract it. That can be downloaded through the following URL. Make sure that you are downloading the correct version that is compatible with your operating system of the computer.

http://developer.android.com/sdk/index.html

After extracting it ,i was able to find the Eclipse IDE version with build in ADT(Android Development Tools) and components that are essentially required to develop the android apps. I would like to thank to the contributors and the team members of the ADT bundle project team to save my time. By the way, if you wish to configure your existing Eclipse IDE as android development environment, you can refer the following links to do so.

http://developer.android.com/sdk/installing/installing-adt.html

Lets start with the project development now.  As a practice we will try to develop a simple  “Hello World” application to understand the android project structure. You can refer the following link to
create the simple App.

https://developer.android.com/training/basics/firstapp/creating-project.html

once the project is built, it took a long time to load the application on the AVD(Android Virtual Device) emulator and I felt like uncomfortable of wasting such time. Therefore I tried to test the app in my mobile and it took only few seconds. But first time I was deploying my app on the mobile it gives me the following error.

INSTALL_FAILED_INSUFFICIENT_STORAGE

The INSTALL_FAILED_INSUFFICIENT_STORAGE error is the bane of every Android developer's life. It happens regardless of app size, or how much storage is available.

There is a simple workaround. If your test device is running Android 2.2 or later then add the android:installLocation attribute to your application's manifest file, with the value "preferExternal". This will force the app to be installed on the device's external storage, such as a phone's SD card.
For example:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.andrewsmith.android.darkness"
    android:installLocation="preferExternal"

I hope that this will be helpful for the new android developers to start their android development on the correct track. If you have any question, you can contact me on chathuranga.t@gmail.com or www.chathurangaonline.com

Cheers
Chathuranga