Tuesday, April 3, 2007

Hello World with standalone Java Persistence, Hibernate and HSQLDB

Lately just started reading (& learning) EJB3. Because of a slow PC at home, I needed to be able to run code for the Java Persistence API in the standalone mode, without the overhead of a huge database or app server. So, I rustled up this guide to get up and running with Java Persistence. Basically all you need is a database and an implementation of the persistence API. We will use HSQL and Hibernate Entity Manager respectively. Hibernate Entity Manager runs on the Hibernate core, so will need that too.

Step 1: You will need Java 5. Get it from http://java.sun.com

Step 2: Download HQSLDB from http://hsqldb.org. Extract into some folder (eg. D:\hsqldb)

Step 3: Download the Hibernate Entity Manager from http://hibernate.org. Extract into some folder. (eg. D:\hibernate-entitymanager-3.2.1.GA)

Step 4: Download the Hibernate Core from http://hibernate.org. Extract into some folder. (eg. D:\hibernate-3.2)

Step 5: Set up the database
  • Create a new folder for all database related files we will create in this step. Lets call it 'db_stuff'.
  • Create a server.properties file. We will name our database 'think'. Configuration parameters should be as below:
server.database.0 file:./think
server.dbname.0 think
  • Start the database in the server mode by running the following from the command line (Better still put this in a batch file)
java -cp D:\hsqldb\lib\hsqldb.jar org.hsqldb.Server
  • You can use the HSQLDB DatabaseManager to view this database. Run the following from the command line to invoke the tool.
java -cp D:\hsqldb\lib\hsqldb.jar org.hsqldb.util.DatabaseManager
In the "Connect" dialog, select the following options:
Type: HSQL Database Engine Server
Driver: org.hsqldb.jdbcDriver
URL: jdbc:hsqldb:hsql://localhost/think
User: sa
Password:

Step 6: Now the standalone. Add the following jars to your project classpath:
  • hsqldb.jar from D:\hsqldb\lib\hsqldb.jar
  • hibernate3.jar from D:\hibernate-3.2
  • all jars from D:\hibernate-3.2\lib\
  • hibernate-entitymanager.jar from D:\hibernate-entitymanager-3.2.1.GA
  • all jars from D:\hibernate-entitymanager-3.2.1.GA
  • Whew!
Step 7: Create the persistence configuration
Create a file named persistence.xml, the persistence configuration file. This file needs to be within a META-INF folder in your classpath. If you are compiling all your classes into a folder, say 'classes', create a META-INF folder under 'classes', then create the persistence.xml file in META-INF. The file should look like below:

<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" version="1.0">

<persistence-unit name="think" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/think"/>
</properties>
</persistence-unit>
</persistence>

Note that the transaction-type is RESOURCE_LOCAL. This is required for standalone environments. Also note the "hibernate.connection.url" matches the URL you use to connect from the HSQL DB Manager to the database, jdbc:hsqldb:hsql://localhost/think

Step 8: Create an entity class, BroadcastMessage.java

package com.blogspot.thought_bytes;

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

@Entity
public class BroadcastMessage {

@Id
private long id;

private String message;

public long getId() {
return id;
}

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

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}


Step 9: Create a harness to interact with the persistence layer, ClientHarness.java

package client;

import com.blogspot.thought_bytes.BroadcastMessage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.EntityTransaction;


public class ClientHarness {

public static void main(String[] args) {
//Use the persistence.xml
EntityManagerFactory emf = Persistence.createEntityManagerFactory("think");
EntityManager em = emf.createEntityManager();

//
EntityTransaction tx = em.getTransaction();
tx.begin();

//Create and initialize an entity instance
BroadcastMessage mb = new BroadcastMessage();
mb.setId(1);
mb.setMessage("Hello World");

//Persist using the entity manager
em.persist(mb);

//Save
tx.commit();

em.close();
emf.close();

}
}

Run the above.

Go back to the database manager and refresh the view. You should be able to see a new tabel "broadcastmessage". If you query this table you should get the following:

ID MESSAGE
-- -------
1 Hello World


That's it! And now the real hard work begins... :)

Cheers,
Aldrin

36 comments:

Anonymous said...

Your step 6. is not good. You do NOT have to add all libraries that come with the Hibernate distribution. Read the README to find out the set of required libraries (only a handful).

thought-bytes said...

Anonymous,

If you are referring to the Hibernate Entity Manager README then that says you require the following libraries:
ejb3-persistence.jar
hibernate-annotations.jar
javassist.jar
jboss-archive-browsing.jar

However, you will still need to add the core hibernate libraries. I couldn't get it to work without the rest of the jars.

Anyway, just wanted a quick "get up and running" setup. It's much easier to simply add all jars from a folder than selectively pick them :)

Alexander Shvets said...
This comment has been removed by the author.
Alexander Shvets said...

Hi,

Your explanation is good, but it involves a loot of actions to do. I prefer to use maven 2 to automate this process completely. Let's take a look here:

http://scriptlandia.blogspot.com/
2007/04/how-to-build-java-
presistence-example.html

Mirror Spock said...

I got your program to work and I have a question: just where is the database stored?

thought-bytes said...

Mirror Spock,

The database is actually the set of files 'think.*' that would have been created in the 'db_stuff' folder that you created in Step 5. There will be a
think.lck
think.log
think.script
think.properties

If you open think.script, you will see sql statements corresponding the your database.

Mirror Spock said...

Is it possible to set up the database without the server step? I want to write a database program that needs nothing but itself to run.

thought-bytes said...

mirror spock,

Not sure what you meant, but if you wish the database to start along with your app, it's possible with HSQL at least(there is a standalone mode). If you have some other database already running, then you will need to configure the persistence.xml accordingly in Step 7.
Hope this helps.

Cheers,
Aldrin

Mirror Spock said...

Aldrin,

How does one start HSQL in standalone mode? I'm trying to figure out how to get a completely standalone program to work.

Thanks.

thought-bytes said...

Mirror Spock,

Check out the documentation at
http://hsqldb.org/doc/guide/ch01.html#N101A8.
It's fairly easy to setup. Let me know if you need more help.

Cheers,
Aldrin

Mirror Spock said...

Aldrin,

Thanks for the info. What I'm looking for is a way to do the persistence example in this article without all the server stuff. I'd like to be able to run the app without starting up the database in server mode. Is that even possible?

Thanks.

Mirror Spock said...

I have another question. How does HQSQL know that db_stuff is where all the database info is to be stored? I didn't see anything in the server properties file or the persistence.xml that told HQSQL where to go.

How would I tell it to put the db info in some other directory, or even in the directory where the actual jar file will reside?

Mirror Spock said...

Yet another question: What type of table is your example setting up? Is it a cached table or a memory table? I can't tell from the persistence.xml or the code. How would one set up a cached table for persistence?

Thanks.

thought-bytes said...

Mirror Spock,
You can start the database from within your application like this,
... Class.forName("org.hsqldb.jdbcDriver");
Connection c =
DriverManager.getConnection(
"jdbc:hsqldb:file:d:/db_files/think", "sa", "");
...

Notice the "file:d:/db_files/think" . That's how HSQLDB knows where to put the files. It can be a relative or absolute path. The point is that the database setup step is totally independent of the rest of the article. persistence.xml is used to define the connection to this database. Later you may want to switch to another database, like MySQL, and all you would need to update (hopefully) is the persistence.xml file.

Once again, the cached or memory database is really dependent on the database. If you replace the above connection URL with "jdbc:hsqldb:mem:think" , then it would be a in-memory database, and this applies only to HQLDB.

Mirror Spock said...

Aldrin,

Thanks for the help, I finally got everything to work smoothly.

Mirror Spock said...

I spoke too soon. It doesn't seem to be creating the database now. There's no think.script file with the insertions.

Aldrin M said...

Hmm...which of these did you use ? the "jdbc:hsqldb:file:d:/db_files/think" or the "jdbc:hsqldb:mem:think" ?

Mirror Spock said...

I used "jdbc:hsqldb:file:d:/db_files/think".

What I still am not sure of is how to tell HSQLDB to use a folder other than db_stuff.

Anonymous said...

Hi,

I am trying to run hsqldb in standalone mode.

Here is what I have done :

1. In hibernate.cfg.xml I have :

a. property name="connection.driver_class">org.hsqldb.jdbcDriver /property>

b. property name="connection.url">jdbc.hsqldb.file:data/db/mydb /property>

2. In Java code :

Class.forName(org.hsqldb.jdbcDriver);
Connection connection = DriverManager.getConnection(jdbc.hsqldb.file:data/db/mydb);

Now when I am using it from netbeans i.e running it from within netbeans - it runs fine.

But when I use the jar file generated by netbeans - the application creates new database files and as such cannot find the files and stuff.

---------------------------------

Here is my folder structure :

src
-...
-...
-...
lib
-...
-...
data
- db - mydb

The generated jar doesn't copy the data folder to dist folder.

------------------------------

Even if I put data folder inside src - it doesn't work (but this time myApplication.jar folder does have the data folder inside it)

------------------------------

Any help would be much appreciated...

Aldrin M said...

It would look in the classpath for the db files. So you would have to place them relative to that. You can also try an absolute path, which would be preferable in this case

jl2tho said...

Thanks a lot for your post. It helps me a lot to handle my EJB entities with HsqlDb.
I'm using the tag : @GeneratedValue(strategy=GenerationType.SEQUENCE) for the Id. Like this I do not need anymore to set my id. It's automatically created. You just need to check that you're Id is a int.

Minhajkk said...

i m a facing an exception at run time

Exception in thread "main" java.lang.NoClassDefFoundError: javax/persistence/Persistence
at ClientHarness.main(ClientHarness.java:13)

note:for a quick review i just add all jars(that you mentioned at ste6 ) into jdk1.5.0_14\jre\lib\ext folder.

bleitner said...

I've followed these instructions, although I used my own entity and test classes. Before it even gets there, however, I get:
javax.persistence.PersistenceException: No Persistence provider for EntityManager named think

I have the persistence.xml both in a META-INF folder off the root and also in a package called data that contains my entity.

I've searched the web and found various references to this issue, but nothing works.

Anonymous said...

You may also throw HSQLDB functions here, so it is a bit easier on more complex Hibernate files:

Use HSQLDB Functions with Hibernate Mapping Files

srinivas said...

Good Tutorial for Hibernate beginners. I was able to configure and execute hibernate from eclipse using the hsqldb command line options you had given which really helped me start the db instantly.

I have observed that if you do not create the server.properties file
a default test database is created with test.properties file.

Also in server mode 2 files are created when database is started they are test.lck and test.log and when the db is shutdown both the files go away. The test.script file is used to recreate the db and stmts everytime when the database is started.

I need to check the in memory mode to see the behaviour.

Vatsala said...
This comment has been removed by the author.
Vatsala said...

THis post is very good. Could you give me ideas on how i could use the same entity manager to run a "select * from table" query???

Vatsala said...

hi.. i figured it myself.. one just has to use the query "from [entity-name]" in the named queries to fetch the data. But pls note that if the entries in the column which represents Id are not distinct and unique, then the result set object will not show all the records. this is because Hibernate maps a resultset to an entity, and when a repeat value is read in the resultset, it thinks "this data is already there" and does not use the other column values of the duplicated id.

Anonymous said...

you have a nice site.thanks for sharing this site. various kinds of ebooks are available here

http://feboook.blogspot.com

Hans said...

THank you fpr sharing your experiences - were very helpful fpr me.

Helen Neely said...

I know this is a bit old, but I just tried it and found it to be easy to run. Thanks for posting it.

JKoder said...

Hi, First of all, I would like to say it's a very nice example. The following jars needed to be included for running this application.

antlr-2.7.6.jar
common-collections.jar
dom4j-1.6.1.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate-testing.jar
javaassist-3.12.0.GA.jar
jta-1.1.jar
slf4j-api-1.6.1.jar
sl4j-jdk14-1.6.1.jar

I have used the hibernate-distribution-3.6.0.Final for running this sampe application

fauzan said...

it's very usefull example for standalone application but why the process is slow, when the query is executed ....??? Is there way to optimize the speed of the process ..?

bucksboy said...

Good article - there should be more like this, self-contained, a clear and precise set steps.

I am going through the Maven learning curve currently, it can be tough but the investment does pay off. You wonder how people get by without it.

Regards, Mark.

siva said...

Hi,
How to read a .script file which has all the database script from the persistence.xml file. My requirement is to create a table in memory using the .script file and delete it once the application stops. how do i achieve it?
thanks

qinbincai123 said...

Who is using the arm of Qiu Jin, for us to put up a brilliant sky?
Who is using the hard-working hands, happy hiehwfdh for us to build a home?
Are you, father, a great name but Ordinary! Father of a mountain.
Wholesale New Era Hats
Cheap 59fifty Hats
Cheap New Era Hats
New Era Snapback Hats
New Era Fitted Hats