JPA是Java Persistence API的简称。
JPA的优势:
1、程序员操作很简单,代码简单 entityManager.persist(employee)
2、直接面向对象操作
3、提供世界级数据缓存(现在几乎所有的ORM框架的缓存都是学的Hibernate) 一级缓存,二级缓存,查询缓存(空间换速度)
4、数据库移植性很强,很少的修改(通过配置方言搞定)把各种数据库抽取了一个方言接口不同数据库实现一个方言接口,如果换了数据库,必须修改方言实现,驱动jar文件,连接数据库信息。
我们一般在中小型项目中可以使用JPA作为持久层框架,面向对象的思想十分方便。然而项目比较大建议使用MyBatis作为持久层框架。
接下来就开始实现JPA。
首先是核心配置文件persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="cn.itsource" transaction-type="RESOURCE_LOCAL">
<properties>
<!--连接数据库的用户名-->
<property name="hibernate.connection.username" value="root"/>
<!--连接数据库的密码-->
<property name="hibernate.connection.password" value="123456"/>
<!--连接数据库的驱动-->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url地址-->
<property name="hibernate.connection.url" value="jdbc:mysql:///jpa"/>
<!--使用不同的方言,底层会生成不同的sql语句-->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<!--
建表策略 是否自动生成表
create:先删除再创建
create-drop:先删除再创建再删除(只针对于entityManagerFactory关闭的情况)
真实项目开发不会使用
update(只增不减):如果没有表则创建表,如果有表就按照正常的业务操作
如果domain中已有字段,但是表中不存在,他会自动创建该列;项目开始一般都是用update
validate:把domain的字段与数据库中的表进行校验,满足条件,正常运行,不满足条件,直接报错
1.校验domain中的数据类型与数据库中的数据类型是否一致
2.校验domain中的属性有,但数据库中没有该属性,报错
-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!--是否显示sql语句-->
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
二、来一个JavaBean(即domian类)
package cn.itsource.domain;
import javax.persistence.*;
@Entity//该类交给jpa进行管理
@Table(name="t_employee")//类映射的表名
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "e_id")
private Long id;
private String username;
@Column(name = "pwd")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
三、抽取一个BaseDao方便以后使用
package cn.itsource.base;
import java.util.List;
/**
* 定义domian对象的普通增删改查方法
*/
public interface IBaseDao<T> {
void save(T t);
void update(T t);
void delete(Long id);
T queryOne(Long id);
List<T> queryAll();
}
四、BaseDaoImpl实现BaseDao接口
已经实现了最基本的增删改查功能,后续只需要继承这个BaseDaoImpl即可
package cn.itsource.base.Impl;
import cn.itsource.base.IBaseDao;
import cn.itsource.util.JPAUtil;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import java.util.List;
public class BaseDaoImpl<T> implements IBaseDao<T> {
private EntityManager entityManager=null;
private EntityTransaction transaction=null;
//定义一个Class类型
private Class<T> clz;
//这是从子类传过来的具体的domain类型
public BaseDaoImpl(Class<T> clz){
this.clz=clz;
}
@Override
public void save(T t) {
//先获取连接池对象
try {
entityManager = JPAUtil.getEntityManager();
//添加数据,先开启事务
transaction = entityManager.getTransaction();
//开启事务
transaction.begin();
//添加数据
entityManager.persist(t);
//提交事务
transaction.commit();
} catch (Exception e) {
if(entityManager==null){
//如果entityManager为空即可能发生的异常,此时应该进行回滚操作
transaction.rollback();
}
e.printStackTrace();
} finally {
if(entityManager!=null){
//关闭资源
entityManager.close();
}
}
}
@Override
public void update(T t) {
try {
entityManager = JPAUtil.getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.merge(t);
transaction.commit();
} catch (Exception e) {
if(entityManager==null){
transaction.rollback();
}
e.printStackTrace();
} finally {
if(entityManager!=null){
//关闭资源
entityManager.close();
}
}
}
@Override
public void delete(Long id) {
try {
entityManager = JPAUtil.getEntityManager();
//先根据id在数据库中查找一条持久化数据
T t = entityManager.find(clz, id);
//删除需要开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.remove(t);
transaction.commit();
} catch (Exception e) {
if(entityManager==null){
transaction.rollback();
}
e.printStackTrace();
} finally {
if(entityManager!=null){
//关闭资源
entityManager.close();
}
}
}
@Override
public T queryOne(Long id) {
T t=null;
try {
entityManager = JPAUtil.getEntityManager();
t = entityManager.find(clz, id);
return t;
} catch (Exception e) {
e.printStackTrace();
} finally {
if(entityManager!=null){
//关闭资源
entityManager.close();
}
}
return t;
}
@Override
public List<T> queryAll() {
List<T> list=null;
try {
entityManager = JPAUtil.getEntityManager();
String jpql="select o from "+clz.getName()+" o";
Query query = entityManager.createQuery(jpql);
list = query.getResultList();
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
if(entityManager!=null){
//关闭资源
entityManager.close();
}
}
return list;
}
}
五、来个测试类测试功能
package cn.itsource;
import cn.itsource.dao.EmployeeDao;
import cn.itsource.domain.Employee;
import org.junit.Test;
import java.util.List;
public class EmployeeTest {
EmployeeDao employeeDao = new EmployeeDao(Employee.class);
@Test
public void TestSave(){
List<Employee> employees = employeeDao.queryAll();
for (Employee employee : employees) {
System.out.println(employee);
}
}
}
得出结果控制台打印
到这里就已经实现了JPA的功能了 其他的增删改功能都已经实现了 各位有空可以自行测试一把。
后续会说明一下SpringDataJPA与Spring的集成,即SSJ框架的实现。