JPA(Java Persistence API)并不是一套持久层的框架,而是一套规范,它提倡以面向对象的方式来对对象进行持久化操作,而不是面向数据库的方式持久化对象,开发人员不再需要编写SQL语句来实现实体的持久化操作。基于JPA规范上去实现持久层,这才形成了一套持久层的框架(例如Hibernate、TopLink、JDO这些都是实现了JPA规范的的持久层框架)。也就是说,实现了JPA规范的持久层框架,那么你可以用面向对象的方式去对java实体对象进行增删改查的操作,而不用自己去编写SQL。
需要学习JPA,首先需要把环境搭起来,这里选择实现JPA规范的持久层框架是Hibernate,版本为5.2.11.Final,并且采用maven进行依赖包的管理,具体步骤如下:
1、创建Maven项目,这一步比较简单,可以直接在IDE创建。
2、添加hibernate-entitymanager依赖包:使用Hibernate来进行实体的管理,实现实体的CRUD操作,我们只需要引入这个hibernate-entitymanager依赖包即可,其它需要依赖的包将由maven自动引入,这样我们就不用关系具体需要依赖哪些jar包了。当然,junit也是必不可少的。所以需要引入的jar包就两个,简单方便:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.lzj.jpagroupId>
<artifactId>jpaartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>jpaname>
<url>http://maven.apache.orgurl>
<properties>
<project.hibernate.version>5.2.11.Finalproject.hibernate.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-entitymanagerartifactId>
<version>${project.hibernate.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.32version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
dependencies>
project>
3、JPA需要一个persistence.xml文件,这个文件可以定义持久化单元、数据库连接信息、事务属性、持久化的提供者等。所谓的持久化单元,就是一堆实体类的集合,在该文件内可以定义多个持久化单元,但是各个持久化单元的名称必须唯一,不可重复。另外,JPA要求把persistence.xml源码目录的META-INFO目录下。persistence.xml内容如下:
<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_2_0.xsd"
version="2.0">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="" value=""/>
<property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="mysqlAdmin" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8" />
properties>
persistence-unit>
persistence>
在该文件我们定义了一个名为persistenceUnit的持久化单元,同时定义了事务属性,数据库连接信息以及持久层框架的一些属性等,这里简单介绍一下几个属性:
(1)、transaction-type:定义事务的类型。事务类型分为本地事务和全局事务。本地事务通常是在一个库内实现的事务,由connection控制。而全局事务是跨库的事务。我们这里只是操作单一的库,所以选择的是本地事务;
(2)、hibernate.dialect:使用的方言,这大家都知道,我这里使用的是mysql数据库,所以选择mysql方言;
(3)、hibernate.hbm2ddl.auto:这里可以定义持久层框架要如何更新数据库表结构。前面已经说了,实现了JPA规范的持久层框架是面向对象的,所以不应该手动创建表或者更新表,而应该交由持久层框架实现。该配置项有以下几个可配置值:
create-drop:每次加载实体操作工厂(hibernate是SessionFactory、JPA是EntityManagerFactory)时根据model类生成表,但是实体操作工厂一关闭,表就自动删除;
update:第一次加载实体操作工厂时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载实体操作工厂时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会;
validate:每次加载实体操作工厂时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
(4)、hibernate.show_sql:在操作实体的过程中是否需要在控制台打印具体的SQL语句。true为打印,false不打印。
4、定义实体:在定义个实体时,可以通过很多的注解去维护与数据库内表的对应信息,当然也可以使用XML文件去维护。我这里是选择使用注解去维护。比如我定义了一个Persion实体,内容如下:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="tb_persion")
public class Persion {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private Integer id;
@Column(name="s_name")
private String name;
@Column(name="i_age")
private Integer age;
/**
* 底层使用代理创建实体类,需要提供一个无参的构造函数
*/
public Persion(){}
public Persion(String name, Integer age){
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
使用注解解释如下:
@Entity:标注在类上,标识这是一个实体,表示需要交给持久层框架去实现该实体的持久化工作;
@Table:标注在类上,定义该实体与数据库的哪个表对应,也就是定定义该实体对应的数据库中的表名,具体名称由该注解的name属性指定;
@Id:标注在实体属性上,标识该实体属性是唯一标识,即主键;
@GeneratedValue:标注在实体属性上,定义主键的生成策略,生成策略由由该注解的strategy属性指定,具体生成策略有以下四个取值:
@Column:标注在实体属性上,定义该实体属性对应数据库表的哪个字段,具体字段名由该注解的name属性指定
注意:由于持久层框架一般是采用反射机制操作实体类,所以一般需要提供一个无参的构造函数。
5、编写测试类,代码如下:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
import junit.framework.TestCase;
public class PersionTest extends TestCase {
@Test
public void testPersion(){
EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistenceUnit");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
em.persist(new Persion("lzj", 26));
em.getTransaction().commit();
em.close();
factory.close();
}
}
这里需要说明三点:
(1)、在创建EntityManagerFactory(实体管理器工厂)的时候根据我们定义的持久化单元名称去创建实体管理器工厂,在创建实体管理器工厂就已经实现了创建表、更新表的动作;
(2)、persist(Object):方法实现对应实体持久化到数据库中,就是真正的插入操作,可开启事务进行操作;
(3)、对应实体管理器、实体管理器工厂类需要在使用之后进行关闭资源;
经过以上几个步骤,就实现了JPA+Hibernate+Maven环境的搭建,完成后的项目结构如下:
在运行测试类时候,应该能在数据库看到相应的表和数据,同时,如果设置了打印具体sql属性,那么执行完之后可以在控制台下看到打印的具体sql: