Translation: Springside team reprint please indicate the source.
This article provides a simple Spring framework standalone environment, how to step-by-step to develop JPA wizards. The JPA specification was first created by the persistence mechanism of EJB 3.0, which is recognized as a mechanism for the simple pojos persistence. You can start to feel the power of JPA in your favorite IDE by configuring a little Spring bean with a few jars in the classpath. Here we are using Glassfish JPA-an open source project based on the Oracle ' s TopLink ORM framework.
initialization Settings Ensure that you are using Java 5 (a prerequisite for JPA in EJB 3.0). Download GlassFish JPA jar from https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html (note: I'm using "v2_build_ 02″jar, but this version should also be back-compatible.) Extract from the "installer" Jar and run: Java-jar glassfish-persistence-installer-v2-b02.jar add Toplink-essentials.jar to your classpath Add the database driver jar (I'm using version 1.8.0.1 's Hsqldb.jar as an example, but in fact you can fit into another database with little change) Join 2.0 M5 The above version of the Spring Jar (HTTP://SOURCEF orge.net/project/showfiles.php?group_id=73357)-Spring.jar-spring-jpa.jar-spring-mock.jar Finally, put these jars Also add to your classpath:-Commons-logging.jar-log4j.jar-junit.jar
domain models (domain model)
In this example we only have a destination listing 3 simple domain model. Note that we use annotation in this example. When using JPA, you typically choose to use annotation or XML files, or both, to specify ORM (object-relational mapping) meta data. Here, we just chose to use the annotation alone, because we just need to add a short description to the code in domain model to be able to do it right away. First, look at the restaurant restaurant Class:package Blog. Jpa. Domain
Import Java.util.Set;
Import Javax.persistence.CascadeType;
Import javax.persistence.Entity;
Import Javax.persistence.GeneratedValue;
Import Javax.persistence.GenerationType;
Import Javax.persistence.Id;
Import Javax.persistence.JoinColumn;
Import javax.persistence.JoinTable;
Import Javax.persistence.ManyToMany;
Import Javax.persistence.OneToOne;
@Entity
public class Restaurant {
@Id
@GeneratedValue (strategy = Generationtype.auto)
Private long ID;
private String name;
@OneToOne (cascade = Cascadetype.all)
private address address;
@ManyToMany
@JoinTable (inversejoincolumns = @JoinColumn (name = "entree_id"))
Private set<entree> entrees;
Public long getId () {
return ID;
}
public void SetId (long id) {
This.id = ID;
}
Public String GetName () {
return name;
}
public void SetName (String name) {
THIS.name = name;
}
Public Address getaddress () {
return address;
}
public void setaddress (address) {
this.address = address;
}
Public set<entree> getentrees () {
return entrees;
}
public void Setentrees (set<entree> entrees) {
This.entrees = entrees;
}
}
Adderss class:
Package blog.jpa.domain;
Import Javax.persistence.Column;
Import javax.persistence.Entity;
Import Javax.persistence.GeneratedValue;
Import Javax.persistence.GenerationType;
Import Javax.persistence.Id;
@Entity
public class Address {
@Id
@GeneratedValue (strategy = Generationtype.auto)
Private long ID;
@Column (name = "Street_number")
private int streetnumber;
@Column (name = "Street_name")
Private String StreetName;
Public long getId () {
return ID;
}
public void SetId (long id) {
This.id = ID;
}
public int Getstreetnumber () {
return streetnumber;
}
public void Setstreetnumber (int streetnumber) {
This.streetnumber = Streetnumber;
}
Public String Getstreetname () {
return streetname;
}
public void Setstreetname (String streetname) {
This.streetname = StreetName;
}
}
Then, entree class:package Blog. Jpa. Domain
Import javax.persistence.Entity;
Import Javax.persistence.GeneratedValue;
Import Javax.persistence.GenerationType;
Import Javax.persistence.Id;
@Entity
public class Entree {
@Id
@GeneratedValue (strategy = Generationtype.auto)
Private long ID;
private String name;
Private Boolean vegetarian;
Public long getId () {
return ID;
}
public void SetId (long id) {
This.id = ID;
}
Public String GetName () {
return name;
}
public void SetName (String name) {
THIS.name = name;
}
public Boolean Isvegetarian () {
return vegetarian;
}
public void Setvegetarian (Boolean vegetarian) {
This.vegetarian = vegetarian;
}
}
As you can see, not all field needs to be annotation. JAP uses default values (for example, using column names in a datasheet to match property names exactly), so in many cases you don't need to specify metadata explicitly. Note that in the entree class, I did not add annotation for string property "name" or Boolean attribute "vegetarian".
However, in the address class, I used annotation because I didn't want to use the column names in the database tables as the default names (for example, I use "street_name" and the default is "StreetName"). The most important thing in the ORM mechanism is of course to specify the correspondence between the objects and the database. In the restaurant class, we use @OneToOne to describe its relationship to address, and we use @ManyToMany to describe its relationship with the entree class. Because instances of other classes are also managed by Entitymanager , you can specify the "cascade" rule, such as when a restaurant is deleted, and all associated address will also be deleted at the same time. Below, you will see the test cases for this scenario. Finally, look at the @GeneratedValue that @Id and specify "strategy" to the Id. This metadata is used to describe how the unique key primary keys are generated in the database. For more information on JPA annotation, see the JPA documentation, JSR-220. The best way for the data Access Layer (Layer) is to create a generic interface to hide all implementation details of the persistence layer, so that the system architecture is not affected by the way that JPA is exchanged for other implementations.
This also facilitates the business logic layer, which makes it easier to implement stub or mock tests. Restaurantdao is an interface, noting that it is not dependent on any JPA or Spring classes. In fact, it relies only on its own domain model (in this simple case, only one, that is restaurant):
Package Blog.jpa.dao;
Import java.util.List;
Import blog.jpa.domain.Restaurant;
Public interface Restaurantdao {
Public restaurant FindByID (long id);
Public list<restaurant> findbyname (String name);
Public list<restaurant> findbystreetname (String streetname);
Public list<restaurant> findbyentreenamelike (String entreename);
Public list<restaurant> findrestaurantswithvegetarianentrees ();
public void Save (restaurant restaurant);
Public Restaurant Update (restaurant restaurant);
public void Delete (restaurant restaurant);
}
For the implementation of the interface, I used the Jpadaosupport class of Spring, which provides a convenient way to get jpatemplate. If you're already familiar with Spring JDBC or other ORM technologies, it's easy to get started. Jpadaosupport is optional, it simply provides a way to use jpatemplate more directly through Entitymanagerfactory. Jpatemplate is also optional, and if you don't want Spring's automatic handling of JPA exception transactions, you can avoid using jpatemplate at all. Even so, Spring's Entitymanagerfactoryutils class will help you a lot, and it provides a convenient static way to get shared entitymanager. Here is the specific implementation code:
Package Blog.jpa.dao;
Import java.util.List;
Import Org.springframework.orm.jpa.support.JpaDaoSupport;
Import blog.jpa.domain.Restaurant;
public class Jparestaurantdao extends Jpadaosupport implements Restaurantdao {
Public restaurant FindByID (long id) {
Return Getjpatemplate (). Find (Restaurant.class, id);
}
Public list<restaurant> findbyname (String name) {
Return Getjpatemplate (). Find ("Select R from Restaurant r where R.name =? 1", name);
}
Public list<restaurant> findbystreetname (String streetname) {
Return Getjpatemplate (). Find ("Select R from Restaurant r where R.address.streetname = 1", streetname);
}
Public list<restaurant> findbyentreenamelike (String entreename) {
Return Getjpatemplate (). Find ("Select R-Restaurant R where R.entrees.name like? 1", entreename);
}
Public list<restaurant> findrestaurantswithvegetarianentrees () {
Return Getjpatemplate (). Find ("Select R from Restaurant r where R.entrees.vegetarian = ' true '");
}
public void Save (restaurant restaurant) {
Getjpatemplate (). persist (restaurant);
}
Public Restaurant Update (restaurant restaurant) {
Return Getjpatemplate (). Merge (restaurant);
}
public void Delete (restaurant restaurant) {
Getjpatemplate (). Remove (restaurant);
}
}
Business Logic Layer (service Layer)
Because our main goal is to focus on the implementation of the data access layer JPA, the business logic layer is largely ignored. In a real project, the business logic layer is critical to the architecture of the system as a whole. It is the focus of the separation business (transaction). In general, we all configure transactions through Spring. In the following steps, when you look at the configuration, you will notice that I have provided a "transactionmanager" bean. It provides transaction rollback for each test method in a test case, and it also provides the transaction with methods that use the same "TransactionManager" business logic layer. The code of the database access layer is not responsible for transaction processing, and the occurrence of transaction propagation is automatic, which is ultimately handled by the business logic layer. The configuration of all persistence layer classes in the spring framework is the same, and use Spring jpatemplate to ensure that all DAO shares the same entitymanager.
Configuration
Because I chose to use the annotation mapping relationship, you may have seen a lot of JPA configuration instructions, as I mentioned above, and it can also be configured with XML (in ' orm.xml ' files) to configure the mapping relationship. The other is only required to configure ' Meta-inf/persistence.xml '. In this way, it will be easier because database-related properties can be obtained by entitymanagerfactory. The information needed in ' persistence.xml ' only requires local or global (JTA) transactions. Here are the details of ' persistence.xml ':
<persistence xmlns= "http://java.sun.com/xml/ns/persistence" version= "1.0"