Вы находитесь на странице: 1из 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection

Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

This tutorial will cover Java persistence using Hibernate and and the Dependency Injection pattern. The software used in this tutorial are listed below. The tutorial assumes the installation of the programs under the e:programs directory.

1. Java 1.5 or newer - http://java.sun.com - Eclipse 3.3.1.1 and the Java Development Tool. - http://www.eclipse.org - http://www.eclipse.org/jdt/ - Hibernate Core 3.2.5 - http://www.hibernate.org/344.html - Hibernate Annotations and EntityManager 3.3.0 - http://hibernate.org/397.html - Hibernate Tools - http://www.hibernate.org/255.html - Struts 2.0.11 - htttp://apache.org - Spring 2.08 - http://www.springframework.org/

1 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

Launch Eclipse after all of the software have been installed.

Click from the top menu Window-Open Perspective-Java if your not currently in the Java Perspective.

Create a new Java project by choosing from the menu File-New-Java Project. Call the project hibernate-spring-tutorial.

You must now set up you Java libraries. 1. Select from the menu Window-Preferences. 2. On the left navigation menu select Java-Build Path-User Libraries. 3. Click the New button. 4. Enter hibernate-3.2.5 as the name. Change 3.2.5 to what ever Hibernate version number you are using. 5. Click on hibernate-3.2.5 and then click on the Add Jars button. 6. Navigate to the location of your Hibernate jar files and add the following files to your hibernate-3.2.5 user library. - hibernate3.jar - javassist.jar - antlr-2.7.6.jar - commons-collections-2.1.1.jar - dom4j-1.6.1.jar - cglib-2.1.3.jar - commons-logging-1.0.4.jar - c3p0-0.9.1.jar - jta.jar - asm-attrs.jar - asm.jar Create a user library named hibernate-annotations-3.2.5 and add the following files. hibernate-annotations.jar ejb3-persistence.jar hibernate-commons-annotations.jar

- Create a user library named hibernate-entitymanager-3.3.1 and add the following files - .hibernate-entitymanager.jar

2 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

- hibernate-validator.jar - jboss-archive-browsing.jar - Create a user library named junit-3.8.2 and add the following file. - junit.jar Create a user library named spring-2.0.8 and add the following files. spring-struts.jar spring-web.jar spring-beans.jar spring-context.jar spring-core.jar spring-context.jar spring-core.jar spring-hibernate.jar spring-dao.jar spring-jdbc.jar

- Create a user library named mysql-connector-3.1.12 and add the following file. - mysql-connector-java-3.1.12-bin.jar - Create a user library named struts-2.0.11 and add all files in the struts-2.0.11/lib directory to the library. - Skip this step

Install MySQL, create a database, userreg, and run the 02_userreg.sql script

Reverse Engineer the userreg database. 1. Launch Eclipse if it is not already running. 2. Open the Hibernate Perspective by clicking Window-Open Perspective-Other. Click on Hibernate.

3 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

3. Create a new project by clicking New-Project-Java-Java Project. Name the project userreg-tool. 4. Right mouse click the src folder and click New-Other. Select Hibernate-Hibernate Configuration File (cfg.xml). Accept the default name. Use the values below 1. Session factory name should be blank. 2. Database dialect should be MySQL (InnoDB) 3. Driver class should be org.gjt.mm.mysql.Driver 4. Connection URL shoud be jdbc:mysql://localhost/userreg 5. Default schema should be userreg 6. Username should be userreg 7. Password should be userreg 8. Make sure the "Create a console configuration" option is selected. Click Next 9. Click on the Annotations (jdk 1.5+) 10. Right mouse click the src folder and click New-Other. Select Hibernate-Hibernate Reverse Engineering File (reveng.xml). You can click this step and just use the hibernate.reveng.xml file that is part of this tutorial. 1. Select userreg-tool-src as the parent folder. 2. The file name should be hibernate.reveng.xml. Click the next button. 3. Select userreg-tool in the console configuration list box. Click the refresh button. 4. The left side window will have "Database schema". Select userreg to display a list of tables. Control+Click on each table and click the Include button. 5. Click the Finish button. 6. Create a Hibernate Configuration file. 1. Make sure the Hibernate Configurations window is open by clicking Window-Show View-Hibernate Configurations. 2. Right mouse click the Hibernate Configurations window and select Add Configuration. 3. In the Main window click the Browse button on the Project line. Select userreg-tool. 4. Click on the Configuration file and select the hibernate.cfg.xml file. 5. We are now ready to run the utility to reverse engineer the code using the reveng.xml file. 1. Select from the main menu Run-Hibernate Code Generation-Open Hinbernate Code Generantion Dialog 2. Click on the page icon with a plus (+) symbol. The icon is above "type filter text". 3. Enter userreg-tool as the name. In the configuration list box select the hibernate option. 4. Click the Browse button to select the output directory. Select userreg-tool/src. 5. Click on the "Reverse engineer from JDBC Connection" option. 6. Click on the Setup button. Click on the "Use existing" button. 7. Select userreg-tool/src/hibernate.reveng.xml. Click the OK button. 8. Click on the Exporters tab and select every thing except Generic Exporter. You can always delete things that get generated.

4 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

9. Click on the Common tab and select the two options in the "Display in a favorites menu". 10. Click on the Run button.

After the program has finished running, you will have many .java files in the default package. These are plain old java objects (POJOs). We will use these class files in our userreg application. We will create a junit test application to persist data using POJOs.

Creating the userreg application. 1. Create a new Java project. Click File-New-Project. Select Java Project and click on the Next button. Enter userreg as the project name. Use src as the source folder. 2. Create a package in the userreg application named com.tang.userreg.model. 3. Add user libraries to the application. 1. Right mouse click userreg and select Properties. 2. Click the Add Library button. 3. Click the User Library option and select the Next button. 4. Select all of the libraries that we have created. 5. Copy AddressType.java from usertool/src to userreg/src/com.tang.userreg.model.

We will now create some Java interfaces that serve as the basis of each POJO and action class. Action classes will persist the data.

Create a package named com.tang.userreg.basic. Copy the following files into this package. 1. Model.java 2. Action.java

5 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

3. AbstractModel.java

Model.java is an interface that contains function declarations that are common to all models. Models in this case represents a record in a database table.

BasicModel.java is an abstract class that implements one method of Model.java. It implements the getMyClass() method.

Action.java is an interface that contains function declarations that are common to all action classes or classes that persist data. Notice that the method declaration does not contain any parameters. Parameters are passed in via constructors or setter methods. The values are injected in this matter.

We will need to make some modifications to the AddressType.java file. We will add import statements, annotations, a static variable for serialization, and comment out the "addresses" variable. We will have a POJO that can be used by hibernate to persist data after this major step. 1. We need to import some packages to use annotations in Java. Add the following lines to the AddressType.java file. import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; 2. Add annotations to the AddressType.java file 1. Add annotations to describe the class. The following should be added before "public class AddressType"

6 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

@Entity @Table(name = "address_type") 2. Add annotations to describe the id. This should go before "private Integer id;" @Id @GeneratedValue @Column(name = "id") 3. Add annotation to the name column. This should go before '@Column(name = "name")' @Column(name = "name") 4. Repeat step 3 for the other columns. Make sure the value for name is correct. 5. Add the following line to declare a static variable to AddressType. static final long serialVersionUID = -726287915382955299L; 6. AddressType must implement the Model interface. Add the following lines 1. import javax.tang.userreg.basic.Model; 2. public class AddressType implements Serializable, Model { 3. Implement the equals() and getMyClass() methods. public boolean equals(Model model) { if(model == null || model.getId() == null) return false; AddressType at = (AddressType)model; if(model.getId().intValue() != getId().intValue()) return false; if(!this.name.equals(at.getName())) return false; if(!this.description.equals(at.getDescription())) return false; if(this.isActive != at.getIsActive()) return false; return true; } public Class<?> getMyClass() { return getClass(); } 4. Change "private Integer isActive" to "private int isActive" 5. Comment a couple of lines for now. 1. Add slashes ("//") to "private Set addresses = new HashSet(0);" 2. Comment constructors and functions that uses the addresses variable.

You can check your file against this AddressType.java file.

Create a package named com.tang.userreg.exception. Copy the following file into this package.

7 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

1. UserRegBasicException.java 2. UserRegInvalidIdException.java

Create a folder named META-INF in the src folder. Hibernate by default (per the JPA specs) will look into the META-INF directory for a file named persistence.xml. This file will declare a persistence unit. The persistence unit is a collection of properties that direct Hibernate what to persist. The property hibernate.archive.autodetection will direct Hibernate to look at Java class files and Hibernate .hbm files for tables to persist. The userreg application's POJO classes contain annotations that Hibernate will use to map the class to a table. Hence, we will not ned .hbm files to describe the class to table mapping. The c3p0 properties direct Hibernate to use c3p0 for connection pooling. c3p0 is an open source project

Copy the following file into the new src/META-INF folder. 1. persistence.xml

Copy the following files into this package. 1. DbActionImpl.java

This class implements the Action class. This class can persist any class that implements the Model interface. The methods do not have parameters. This prevents the method from being locked into a concrete implementation. DbActionImpl contains a Model property which gets set through a setter method. Recall that model is a Java plain old Java object (POJO) that represents a record in the database. Let's look at each method in detail. - delete() will remove an object, model, from the database. It uses the JPA Persistence static method to create a factory, emf. Notice that the "userreg" parameter that was used to create the factory. "userreg" was defined in the persistence.xml file. The entity manager factory, emf, will be used to create an entity manager, em. A transaction object, tx, will then be created from the em. The object to be removed, model, is detached from the persistence context. In plain English, Hibernate doesn't know any thing about model. You have to "introduce" model into the conversation (context). We use the em.merge() method to bring model into the context.

8 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

Now that Hibernate is aware of model we can delete it and then commit the transaction. - find() will try to find the model object from the database. The entity manager's find() method requires two parameters. The first parameter is the class name. The second parameter is the id field that represents the primary key of the object. A null value will be returned if the object doesn't exist in the database. - save() will persist the model to the database. The Model interface assumes that the object has a database single auto-generated property identified as id. There are three scenarios that can occur. 1. The id property is null then save() will insert an object. 2. The id property has a value and it exists in the database. save() will update the database with properties of model. 3. The id property has a value and it does not exist in the database. save() will throw an exception. An exception is thrown because the id field is not known to the database. Remember, this field is auto generated. The database should know about it.

We now have the infrastructure to persist data to the AddressType table. We will know add more independent tables. Relationship tables will be discussed later. Please add the following files to the com.tang.userreg.model package. 1. 2. 3. 4. Company.java Dept.java Role.java User.java

We will create classes that will test our persistence framework. The code from the test classes can be adapted to your personal application. Create a package named com.tang.userreg.test. Copy the following file into this package. 1. Test.java

Test.java is a junit test application. Each test scenario has a method that starts with 'test'. Each test method will instantiate an object that implements the Model interface. Then the runMyTest()

9 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

method will execute with the model passed as a parameter.

Let's look at runMyTest(). This method will run a series of test on the model object that was passed into the method. The model object will be set with an invalid ID - an id that does not exist in the database. This should cause an exception. It then tries to insert the object by setting the id to null and then calling DB_ACTION.save(). DB_ACTION is a static variable of type DbActionImpl, our action class. DB_ACTION.save() does not require a parameter to persist because the model was injected into DB_ACTION by calling DB_ACTION.setModel(model). This allows DB_ACTION's other methods such as save(), delete(), and find() to operate without having to require a passed in parameter. runMyTest() will then try to find the newly inserted object. Lastly, the newly inserted object will be deleted.

Let's run the tests. Right mouse click the Test file within Eclipse. Select Debug As-JUnit Test. Use F5 to step into and F6 to step over the code.

We used one action class, DB_ACTION, to maintain our four tables. DB_ACTION class can persist any object that implements the Model interface. No SQL was ever written either.

We have only mapped independent tables. We will now map the user_roles table. This is a union between the users and roles table. Logically, the user_roles table's primary key is the user_id and the role_id. However, having a compound primary key is more complicated to work with. It also is more expensive because it requires more table space. Replacing the primary key with an integer auto-generated key is more efficient. It's also a good design pattern to use a surrogate key as the primary key (http://en.wikipedia.org/wiki/Surrogate_key). Using a surrogate key for user_roles will also allow us to use Model.java and DbActionImpl.java to persist user_roles records. Copy the following file to com.tang.userreg.action package. 1. 2. 3. 4. 5. 6. Address.java CompanyAddress.java CompanyDept.java CompanyDeptRole.java CompanyRoles.java CompanyUsers.java

10 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

7. CompanyUsersRole.java 8. DeptRoles.java 9. UserAddress.java 10. UserRoles.java

The id column has the same annotations as the other classes in the com.tang.userreg.model package. What is different are the user and role properties (variables). The properties are of type User and Role. Let's look at the user property. The annotation @ManyToOne(fetch=FetchType.EAGER) tells hibernate that UserRoles has a Many to One relationship with user. FetchType.EAGER tells hibernate to retrieve the User object when UserRoles is retrieved.

Run the following file in the MySQL userreg database. The SQL file will insert a users and roles record. The records are required before we can test UserRoles.java. 1. 03_test_data_insert.sql

Download the new test class below and run it as a junit application. 1. Test2.java

asdf

11 / 12

Java Persistence with Hibernate, Annotations, and Spring Dependency Injection


Written by John Tang Tuesday, 16 September 2008 09:59 - Last Updated Monday, 22 December 2008 13:23

12 / 12

Вам также может понравиться