Saturday, May 22, 2010

JPA getting started, easy example of JPA, JPA annotation example, JPA with Hibernate

Very basic example of how to implement JPA using hibernate provider for mysql database.

Create one project in Eclipse (say JPABlogTestHibernate) add these jar files.

1. log4j-1.2.15.jar
2. mysql-connector-java-3.1.12-bin.jar
3. persistence-api-1.0.jar
4. slf4j-simple-1.4.2.jar
5. cglib-2.1_3.jar
6. cglib-asm-1.0.jar
7. commons-collections-3.2.jar
8. commons-logging-1.1.jar
9. hibernate-core-3.3.1.GA.jar
10. hibernate-entitymanager-3.3.1.ga.jar
11. javassist-3.3.jar
12. jta-1.0.1B.jar
13. jboss-archive-browsing-5.0.0alpha-200607201-119.jar
14. dom4j-1.6.1.jar
15. slf4j-api-1.4.2.jar
16. hibernate-tools-3.2.0.beta9a.jar
17. hibernate-annotations-3.4.0.GA.jar
18. hibernate-commons-annotations-3.1.0.GA.jar
19. antlr-2.7.7.jar

Create one persistence.xml inside src\META-INF folder.
create one package inside src say com.suman
Add these files

Company.java
TestApplication.java
persistence.xml

log4j.xml inside src folder

Company.java (src\com\suman)

package com.suman;
import javax.annotation.Generated;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.apache.log4j.Logger;

/**
* @author Binod Suman
*/

@Entity
@Table(name="blogcompany")
public class Company {
@Id
private int id;
@Column(name="cname")
private String name;
private String city;

@Transient
Logger log = Logger.getLogger(Company.class);

public Company(){};

public Company(String name, String city) {
super();
this.name = name;
this.city = city;
}

public Company(int id, String name, String city) {
super();
this.id = id;
this.name = name;
this.city = city;
}

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 getCity() {
return city;
}


public void setCity(String city) {
this.city = city;
}

}


TestApplication.java (src\com\suman)
package com.suman;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.log4j.Logger;

/**
* @author Binod Suman
*/

public class TestApplication {
Logger log = Logger.getLogger(TestApplication.class);
public static void main(String[] args) {
TestApplication test = new TestApplication();
test.saveCompany();
}

public void saveCompany(){
log.info("Company data is going to save");
EntityManagerFactory emf;
emf = Persistence.createEntityManagerFactory("jpablogPUnit");
EntityManager entityManager = (EntityManager) emf.createEntityManager();
entityManager.getTransaction().begin();
Company company = new Company(110,"TecnoTree","Bangalore");
entityManager.persist(company);
entityManager.getTransaction().commit();
log.info("Company data has been saved");
}
}


Create database table blogcompany inside the sumandb database.
CREATE TABLE blogcompany (
id int(11) NOT NULL,
cname varchar(100) default NULL,
city varchar(100) default NULL,
PRIMARY KEY (id)
)

Now you can run the TestApplication.java and see the log on console
One record has been inserted into blogcompany table.

That's easy ............ :)

If you have question and doubt then please give your comment or if you have any feedback.

Thanks .......... :)

Saturday, May 15, 2010

Spring Transaction using JDBCTemplate, Spring Transaction easy example

Here I am going to show very easy example of Spring jdbcTemplate transaction. First I will write one small example to save data into mysql database without handling any transaction then we will solve problem with use of Spring transation.

Create one project (JDBCTemplateTransaction) in eclipse and add these below mentioned external jar:

1. spring-2.5.6.jar
2. mysql-connector-java-5.1.9.jar
3. log4j-1.2.15.jar
4. commons-logging-1.0.4.jar
5. commons-dbcp-1.2.2.jar
6. commons-pool-1.3.jar

Create one package in src folder say com.suman and add these java files.
1. App.java
2. IDaoOperation.java (Interface)
3. DaoOperation.java

All the code are below.

Create three file inside the src folder
1. project-config.properties
2. project-config.xml
3. log4j.xml

******** code section ************
App.java

package com.suman;

import org.apache.log4j.Logger;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
public static void main( String[] args )
{
Logger log = Logger.getLogger(App.class);
IDaoOperation daoOperation;
log.info( "Check Spring Transaction using jdbcTemplate" );
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("project-config.xml");
daoOperation = (IDaoOperation) context.getBean("daoOperation");
daoOperation.saveStudent();
log.info("THIS IS MAIN METHOD OF SPRING TEST");
}
}

IDaoOperation.java

package com.suman;
/**
* @author Binod Suman
*/
public interface IDaoOperation {

public void saveStudent();

}


DaoOperation.java

package com.suman;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcOperations;

/**
* @author Binod Suman
*/
public class DaoOperation implements IDaoOperation{

private DataSource dataSource;
private Logger log;
private JdbcOperations jdbc;

public void saveStudent(){
String sql = "insert into student (id,name,roll) values (1,'Binod',110)";
executeSQL(sql);
saveHostel();
}

public void saveHostel(){
String sql = "insert into hostel (id,name,roll) values (1,'Yamuna',1)";
executeSQL(sql);
}


public DataSource getDataSource() {
return dataSource;
}

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

public JdbcOperations getJdbc() {
return jdbc;
}

public void setJdbc(JdbcOperations jdbc) {
this.jdbc = jdbc;
}


public void init(){
log = Logger.getLogger(DaoOperation.class);
setDatabase();
}


public void executeSQL(String sql) {
try{
log.debug("exec SQL: " + sql);
jdbc.execute(sql);
}catch(Exception e){
log.error("some problem during executing sql");
}
}

public void executeSQL(Collection<String> sqlList) throws IOException,
SQLException {
for (String sql : sqlList) {
executeSQL(sql);
}
}
public void setDatabase(){
executeSQL("USE sumandb");
}


}


project-config.properties
db.driver = com.mysql.jdbc.Driver
db.url = jdbc:mysql://localhost
db.username = root
db.password = mysql

project-config.xml

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<context:mbean-server/>
<context:property-placeholder location="classpath:/project-config.properties" />

<bean id="daoOperation"
class="com.suman.DaoOperation"
init-method="init" p:dataSource-ref="dataSource"
p:jdbc-ref="jdbc" />

<bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

<!--Infrastructure setup -->

<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource" p:driverClassName="${db.driver}"
p:url="${db.url}" p:username="${db.username}" p:password="${db.password}" />

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>

<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">

<!-- logs to system console -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<param name="Threshold" value="ALL" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />
</layout>
</appender>

<logger name="org.springframework" additivity="false">
<level value="WARN" />
<appender-ref ref="CONSOLE"/>
</logger>

<root>
<level value="ALL" />
<appender-ref ref="CONSOLE" />
</root>

</log4j:configuration>


Create database with name sumandb in mysql in localhost at 3306 port.
Then create the two table

create table
CREATE TABLE `student` (
`id` int(11) NOT NULL,
`name` varchar(90) default NULL,
`roll` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1



create table
CREATE TABLE `hostel` (
`id` int(11) NOT NULL,
`name` varchar(200) default NULL,
`roll` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `FK_hostel` (`roll`),
CONSTRAINT `FK_hostel` FOREIGN KEY (`roll`) REFERENCES `student` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1



RUN THE APPLICATION :

Now run App.java
you will see one record has been inserted into student table and one record into hostel table.

Here student.id is the foreign key for hostel.roll. So without having id (say x) exist in student table you can not save any record into hostel table with roll x.
** IMP **. But I am going to save into both table. I will give id 2 in student table and roll 9 in hostel table.
String sql = "insert into student (id,name,roll) values (2,'Pramod',110)";
String sql = "insert into hostel (id,name,roll) values (1,'Yamuna',9)";
See what is going to happen.

One recrod has been inserted in student table but no new record into hostel table. BUT in student table record should not have been inserted if we will use TRANSACTION.

delete that recrod from student table.
DELETE FROM student WHERE id = 2

NOW I AM GOING TO IMPLEMENT SPRING TRANSACTION.

FIRST WAY TO IMPLEMENT SPRING TRANSACTION.

Change saveStudetn() of DaoOperation.java method and change import:

public void saveStudent(){
TransactionTemplate tt = new TransactionTemplate();
tt.setTransactionManager(new DataSourceTransactionManager(getDataSource()));
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
String sql = "insert into student (id,name,roll) values (2,'Pramod',110)";
executeSQL(sql);
saveHostel();
}
});
}

Change import

import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;



Now you run App.java, there will NOT be any record will get inserted either in Student or hostel table. Transaction has rolled back all the database opeartion if any operation gets fail.

Now change sql:
String sql = "insert into student (id,name,roll) values (2,'Pramod',110)";
String sql = "insert into hostel (id,name,roll) values (2,'Yamuna',2)";

Now run the application.
Both record have been saved successfully.


SECON WAY TO IMPLEMENT SPRING TRANSACTION.

Change saveStudetn() of DaoOperation.java method and change import:

@Transactional (propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public void saveStudent(){
String sql = "insert into student (id,name,roll) values (2,'Pramod',110)";
executeSQL(sql);
saveHostel();
}



Change sql to check whether transaction is working correctly:

String sql = "insert into student (id,name,roll) values (3,'Ayush',120)";
String sql = "insert into hostel (id,name,roll) values (3,'Ganga',9)";

no any record should be inserterd.

Now change sql, and both record should be inserted.
String sql = "insert into student (id,name,roll) values (3,'Ayush',120)";
String sql = "insert into hostel (id,name,roll) values (3,'Ganga',3)";

Thats easy ............... :)


Now I checked with huge data. If any record will not be able to insert then all the previouse record will rolled back.

Changed both method of DaoOpeartion.java

public void saveStudent(){
for(int i=0;i<10;i++){
String sqlStudetn = "insert into student (id,name,roll) values ("+i+",'Ayush',120)";
String sqlHostel = "insert into hostel (id,name,roll) values ("+i+",'Ganga',"+i+")";
executeSQL(sqlStudetn);
saveHostel(sqlHostel);
}

}

public void saveHostel(String sql){
executeSQL(sql);
}


Run the App.java

10 record should be inserted into Student table and 10 records should be inserted into hostel table.

Now add last recrod that should not be insert to avoid foreign key constraints. Then all the previous 10 record will be rolled back;

DELETE FROM hostel;
DELETE FROM student;
@Transactional (propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public void saveStudent(){
for(int i=0;i<10;i++){
String sqlStudetn = "insert into student (id,name,roll) values ("+i+",'Ayush',120)";
String sqlHostel = "insert into hostel (id,name,roll) values ("+i+",'Ganga',"+i+")";
executeSQL(sqlStudetn);
saveHostel(sqlHostel);
}
String sqlHostel = "insert into hostel (id,name,roll) values (10,'Ganga',10)";
saveHostel(sqlHostel);
}


Now run the App.java
and check database, there is no any record has been inserted either in student table or Hostel table.

That's easy .............. :)