Archive for the 'JDBC' Category

04
Jun
10

Hibernate and HSQLDB

This page describes how to setup a project using Hibernate and HSQLDB. A better method would be to use JPA to configure hibernate and use the JPA API directly.

Requirements

  • Java 5
  • Maven
  • Understanding of JDBC and SQL
  • Basic understanding of Relational Databases

Start a new project

Run the following command to generate a new project using a maven archetype.

mvn archetype:generate --batch-mode \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DgroupId=com.test \
  -DartifactId=hsqldbTest

The following maven pom.xml file defines the following dependencies

  • HSQLDB
  • Hibernate and Hibernate Annotations

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>hsqldbTest</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>hsqldbTest</name>
  <url>http://maven.apache.org</url>
<build>
    <plugins>
       <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.0.2</version>
          <configuration>
              <source>1.5</source>
              <target>1.5</target>
          </configuration>
      </plugin>
    </plugins>
</build>
  <dependencies>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>1.8.0.10</version>
    <scope>test</scope>
</dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.2.6.ga</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>3.3.1.GA</version>
    </dependency>

  </dependencies>
</project>

Hibernate Configuration File

The following configuration files defines

  • Connection URL that specifies that the HSQLDB database will be file based, it will be located in the src/main/resources/db folder and the “shutdown” parameter specifies that the database will be persisted to the file when all the connections are closed.
  • Default admin username is “sa” and password is “blank”
  • The connection pooling is turned off by specifying “connection.pool_size” as 0 (hibernates built in pool implementation is really bad. It prevents HSQLDB from properly shutting down. Therefore we turn it off.

src/main/resources/hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.url">jdbc:hsqldb:file:src/main/resources/db/mydbname;shutdown=true</property>
    <property name="connection.username">sa</property>
    <property name="connection.password"></property>

    <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
    <property name="dialect">org.hibernate.dialect.HSQLDialect</property>

    <property name="show_sql">true</property>

    <property name="format_sql">true</property>
    <property name="hbm2ddl.auto">create</property>
 <!--
    * validate: validate the schema, makes no changes to the database.
    * update: update the schema.
    * create: creates the schema, destroying previous data.
    * create-drop: drop the schema at the end of the session.
-->
    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">0</property>
    <property name="current_session_context_class">thread</property>

<mapping class="com.test.hibernate.model.Blog" />

  </session-factory>
</hibernate-configuration>

Entity Bean

src/main/java/com/test/hibernate/model/Blog.java

package com.test.hibernate.model;

import java.util.Date;

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

@Entity
public class Blog {

  private Long id;

  private String subject;

  private String body;

  private Date createdAt;

  @Id
  @GeneratedValue
  public Long getId() {
    return id;
  }

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

  public String getSubject() {
    return subject;
  }

  public void setSubject(String subject) {
    this.subject = subject;
  }

  public String getBody() {
    return body;
  }

  public void setBody(String body) {
    this.body = body;
  }

  public Date getCreatedAt() {
    return createdAt;
  }

  public void setCreatedAt(Date createdAt) {
    this.createdAt = createdAt;
  }
}

Test case

src/test/java/com/test/AppTest.java

package com.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import com.test.hibernate.model.Blog;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

public class AppTest extends TestCase {
    public AppTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(AppTest.class);
    }

    public void testHibernate() throws Exception {
        SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

        Session session = sessionFactory.getCurrentSession();

        Transaction tx = session.beginTransaction();

        Blog b = new Blog();
        session.save(b);

        tx.commit();
// the connection pool implementation in hibernate is bad.
// Either use 3cpo or dbcp or dont use it at all...
// in this example we set the connection pooling off.
// <property name="connection.pool_size">0</property>
    }

}

Run the test case

mvn clean compile test

Related Posts

Appendix

To shutdown the HSQLDB database manually you can issue the following.
//org.hsqldb.DatabaseManager.closeDatabases(0);

03
Jun
10

Rapid Prototyping using HSQLDB

This page describes the process of setting up a simple database for the purpose of rapid development and prototyping.

Background

HSQLDB is a database is implemented purely in Java. It has a very small footprint and can run within the same JVM as the program being tested. Developing database applications using HSQLDB allows developers to rapidly develop and integration test their front end code or business logic without having a live database connection. Since all the data is stored and persisted locally, developers are free to work from locations that might not have database connectivity. For example outside the company firewall.

Requirements

  • Java 5
  • Maven
  • Understanding of JDBC and SQL
  • Basic understanding of Relational Databases

Start a new project

Start the project by creating one using a maven archetype.

mvn archetype:generate --batch-mode \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DgroupId=com.test \
  -DartifactId=hsqldbTest

Once the project is created, then “cd to the project folder” and add the following depencency section in the pom.xml file

pom.xml

 <dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>1.8.0.10</version>
    <scope>test</scope>
</dependency>

Regenerate the eclipse project by typing

mvn eclipse:clean eclipse:eclipse

Import the project into eclipse.

Configuration

There are 2 ways to configure the database.

  • Pure In memory database URL (InMemory): jdbc:hsqldb:mem:databaseName
  • Persistant URL (File system): jdbc:hsqldb:file:databaseFilename

The following is how it was done for this example:

  • File system database was chosen since we want the data to remain persistant after the program ends. The File system databse is s specified in the url.
  • The database files are placed in the location specified in the URL (src/main/resources/db/)
  • The database will be called “mydbname” (database and parent folders will be created if they don’t exist already)
  • The default credentials to use HSQLDB is “sa” and the password is blank. (Specified during JDBC connection)

Test the database

The following test case

  1. creates a table if one does not exit already
  2. inserts some data. Once data is inserted it
  3. selects the data and displays it to the console.

See complete output of the test case below

src/test/java/com/test/AppTest.java

package com.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class AppTest extends TestCase {
	public AppTest(String testName) {
		super(testName);
	}

	public static Test suite() {
		return new TestSuite(AppTest.class);
	}

	public void testApp() throws Exception {
		Class.forName("org.hsqldb.jdbcDriver");
		String url = "jdbc:hsqldb:file:src/main/resources/db/mydbname";
		String username = "sa";
		String password = "";

		Connection connection = DriverManager.getConnection(url, username,
				password);

		Statement statement = connection.createStatement();
		try {
			statement.executeQuery("select * from sec_edgar_filer;");
		} catch (SQLException ex) { // if no table then create one.
			statement
					.execute("CREATE TABLE sec_edgar_filer ( cik VARCHAR(22) NOT NULL);");
		}
		
		try {
			statement.execute("insert into sec_edgar_filer values ( 'Hello World! "
					+ System.currentTimeMillis() + "' );");
			ResultSet resultset = statement
					.executeQuery("select * from sec_edgar_filer;");

			int count = 0;
			while (resultset.next()) {
				System.out.println(resultset.getString(1));
				count++;
			}
			System.out.println("total rows returned: " + count);
			
		} finally {
			try {statement.execute("SHUTDOWN;");} catch (Exception ex) {}
			try {connection.close();} catch (Exception ex) {}			
		}
	}
}

Run the test case

At this point you have 2 options.

  1. Run the test case in eclipse using JUnit test runner
  2. Run the test by executing “mvn test” on the command line.

Either way you will see output similar to this…

Hello World! 1275621161302
Hello World! 1275621164539
Hello World! 1275621179581
Hello World! 1275621424099
total rows returned: 4

Be sure to Shutdown

All you need to do is to issue a SQL SHUTDOWN command to instruct HSQLDB to initiate a shutdown procedure. This is an important step to allow the data in memory to be saved to the disk.

You will notice that 2 files have been created in the src/main/resources/db directory.

  • mydbname.properties – contains the settings for the database.
  • mydbname.script – contains the data for the tables

References

19
Dec
09

database connectivity using spring framework

This page describes the process of setting up database connectivity using a spring framework based application. We are going to use the DriverManagerDataSource provided by the spring framework to get things started.

As stated by its javadoc:

Useful for test or standalone environments outside of a J2EE container, either as a DataSource bean in a corresponding ApplicationContext or in conjunction with a simple JNDI environment.

In other words this is a quick an dirty way of doing it. This is not production ready. In order to make it production ready you need to use database connection pools provided by your Web application container.

Driver Manager Names and Connection URL’s

In order to connect to databases you need one or more of the following items:

  • Driver Manager Class Name
  • URL
  • username
  • password

In some databases all this information is part of the URL in that case you only need a URL. It depends on the database vendor implementation.

Continue Reading about connection pools

Refer to the following page in order to setup a connection pool for quicker database access.

Database Connection Strings

The following is a list of popular databases and their connection strings.

mySQL Connection String

spring configuration

	<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://hostname:3306/dbname"/>
		<property name="username" value="username"/>
		<property name="password" value="xxxxx"/>
	</bean>

	<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
		<constructor-arg><ref bean="dataSource"/></constructor-arg>
	</bean>

Maven dependency

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
</dependency> 

Sybase

Driver: com.sybase.jdbc.SybDriver
URL: jdbc:sybase:Tds:hostname:port/dbname

Oracle

Driver: oracle.jdbc.driver.OracleDriver
URL: jdbc:oracle:thin:myusername/mypassword@//localhost:1521/DBNAME
URL: jdbc:oracle:thin:@localhost:1521:MyDatabase

DB2

com.ibm.db2.jcc.DB2Driver
jdbc:db2://hostname:port/TEST

Microsoft SQL Server

Driver: com.microsoft.jdbc.sqlserver.SQLServerDriver
URL: jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=northwind

Informix

URL: jdbc:informix-sqli://hostname:portnumber/MyDatabase:INFORMIXSERVER=MyServerName
Driver: com.informix.jdbc.IfxDriver

postgresql

URL: jdbc:postgresql:template1
Driver: org.postgresql.Driver

Derby

URL (Network): jdbc:derby://hostname:1527/sample;user=username;password=password
URL (FileSystem): jdbc:derby://hostname:1527/c:/directory/dbname;user=username;password=password
Driver: org.apache.derby.jdbc.ClientDriver

HSQLDB

URL (InMemory): jdbc:hsqldb:mem:aname
URL (File system): jdbc:hsqldb:file:aname
Driver: org.hsqldb.jdbcDriver

17
Dec
09

Querying a Database using Spring JdbcTemplate

This page describes the process of querying data from a database using The Spring Framework’s JdbcTemplate and SimpleJdbcTemplate.

One of the first things that catches our eye when we start using the spring framework is the JdbcTemplate.

The following is the DDL for the table we will be using to run Queries. It holds movie Genre’s. Its a simple table with 2 columns.

CREATE TABLE IF NOT EXISTS `GENRE` (
  `GNR_I` int(11) NOT NULL AUTO_INCREMENT,
  `GNR_X` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`GNR_I`)
)

JdbcTemplate

(legacy) This class is considered legacy. If you want to take advantages of the Java 5 features then use SimpleJdbcTemplate in the next section.

The following code queries the Genre table.

package test;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

@Component("genreDataManager")
public class GenreDataManagerImpl implements GenreDataManager {
	private JdbcTemplate jdbcTemplate;

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	@Autowired
	@Required
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public List<Genre> getAllGenre() {
		List genreList = this.jdbcTemplate.query(
			    "select gnr_i, gnr_x from GENRE",
			    new RowMapper() {
			        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
			            Genre genre = new Genre();
			            genre.setId(rs.getInt(1));
			            genre.setName(rs.getString(2));
			            return genre;
			        }
			    });
		return genreList;
	}
}

SimpleJdbcTemplate

This class takes advantage of varargs and autoboxing, and exposing only the most commonly required operations in order to simplify JdbcTemplate usage. Use this class instead of the plain old JdbcTemplate.

The following is the same thing but using SimpleJdbcTemplate

package test;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.stereotype.Component;

@Component("genreDataManager")
public class GenreDataManagerImpl implements GenreDataManager {
	private SimpleJdbcTemplate jdbcTemplate;

	public SimpleJdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	@Autowired
	@Required
	public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public List<Genre> getAllGenre() {
		List<Genre> genreList = this.jdbcTemplate.<Genre>query(
			    "select gnr_i, gnr_x from GENRE",
			    new ParameterizedRowMapper<Genre>() {
			        public Genre mapRow(ResultSet rs, int rowNum) throws SQLException {
			            Genre genre = new Genre();
			            genre.setId(rs.getInt(1));
			            genre.setName(rs.getString(2));
			            return genre;
			        }
			    });
		return genreList;
	}
}

ApplicationContext.xml

The following file defines the jdbcTemplate and datasource. With these minimal settings you can successfully query a database.

applicationContext.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- The following is used for the @Autowired and @Required, @Resource etc... java.sql.DriverManager -->
	<context:annotation-config/>
	<context:component-scan base-package="test"/>
	<!-- This is a quick and dirty way to setup a datasource -->
	<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
		<property name="url" value="dburl"/>
		<property name="username" value="dbusername"/>
		<property name="password" value="password"/>
	</bean>

	<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
		<constructor-arg><ref bean="dataSource"/></constructor-arg>
	</bean>
</beans>

27
Oct
09

Ibatis 2.3 spring 2.5 Hello World

This page describes a very simple HelloWorld type application being created so that it can be used as a base for more complex projects.

We start out with adding this to an already created pom.xml file.

		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

If you have not done so already add the jdbc drivers for your database. In my case I am using mySQL.

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.9</version>
		</dependency>

regenerate the eclipse project:
mvn eclipse:clean eclipse:eclipse

REturn back to eclipse and refresh the project.

IBatis Main Configuration File

We first start with defining the main configuration file for the Ibatis framework. If you are working with a web application this is typically your WEB-INF folder. If you were using ibatis as a standalone framework you would have needed to put additional configuration entries in this file. However since we are using this with the state of-the-art dependency injection functionality provided by the spring framework.

MappersConfig.xml currently contains the locations of all the xml configuration files of all the individual sqlMap files.

MapperConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
        PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <sqlMap resource="com/vermatech/electronics/repository/ItemDataManager.xml"/>
</sqlMapConfig>

SQL Maps configuration files

Each SQL MAp resource specifies a set of sql statements that may be run against an entity. Inserts, updates, deletes etc are specified within XML syntax. In addition to SQL Statements you may specify additional attributes like how long you want the statements to cache. Aliases may be defined for class names. REsults map for returned results and parameter map for parameters.

Parameters Maps and Result Maps

Here is an example that uses parameters map and results maps explicitly

<typeAlias alias=”product” type=”com.ibatis.example.Product” />
<parameterMap id=”productParam” class=”product”>
         <parameter property=”id”/>
</parameterMap>
<resultMap id=”productResult” class=”product”>
         <result property=”id” column=”PRD_ID”/>
         <result property=”description” column=”PRD_DESCRIPTION”/>
</resultMap>
<select id=”getProduct” parameterMap=”productParam”
         resultMap=”productResult” cacheModel=”product-cache”>
    select * from PRODUCT where PRD_ID = ?
</select>

If you want to keep the xml configuration simple you can have Ibatis make educated guesses on how to map a Bean to Parameter and from Results back to beans. There is a slight performance consequence in that this approach requires accessing the ResultSetMetaData. This limitation can be overcome by using an explicit resultMap. Result maps are described in more detail later in this document. This uses the auto mapping feature of the framework which could be slower than if you specified the mappings yourself.

Here is an example that allows the sqlMap to make educated guesses about the mappings

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
  PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
  "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace=”Product”>
   <select id=”getProduct” parameterClass=” com.ibatis.example.Product”
                              resultClass=”com.ibatis.example.Product”>
         select
            PRD_ID as id,
            PRD_DESCRIPTION as description
         from PRODUCT
         where PRD_ID = #id#
   </select>
</sqlMap>

Since the developer is specifying SQL witin XML you need the ability to escape characters that would appear in xml. An example is the < and > signs.

<select id="getPersonsByAge" parameterClass=”int” resultClass="examples.domain.Person">
         SELECT *
         FROM PERSON
         WHERE AGE <![CDATA[ > ]]> #value#
</select>

SQL Fragments

In order to reduce SQL Code duplication you can use things like Fragments but keep in mind that it does increase the amount of testing effort if something in the common fragment changes.

Here is an example:

<sql id="selectItem_fragment">
         FROM items
         WHERE parentid = 6
</sql>
<select id="selectItemCount" resultClass="int">
         SELECT COUNT(*) AS total
         <include refid="selectItem_fragment"/>
</select>
<select id="selectItems" resultClass="Item">
         SELECT id, name
         <include refid="selectItem_fragment"/>
</select>

Auto generated keys

Supported by using the following XML code

<!—Oracle SEQUENCE Example -->
<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">
    <selectKey resultClass="int" >
         SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL
    </selectKey>
    insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)
    values (#id#,#description#)
</insert>
<!— Microsoft SQL Server IDENTITY Column Example -->
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">
    insert into PRODUCT (PRD_DESCRIPTION)
    values (#description#)
    <selectKey resultClass="int" >
         SELECT @@IDENTITY AS ID
    </selectKey>
</insert>

Calling Stored Procedures

<parameterMap id="swapParameters" class="map" >
  <parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
  <parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
</parameterMap>
<procedure id="swapEmailAddresses" parameterMap="swapParameters" >
  {call swap_email_address (?, ?)}
</procedure>

The next steps are to start coding your CRUD operations on your objects. I talk about this in more detail at the following page




Follow

Get every new post delivered to your Inbox.

Join 34 other followers