JPA入门
一、JPA
(一)概念
- 是Java Persistence API的简称
- 是对象关系映射(ORM) 规范
- 最底层的操作还是JDBC(引入驱动包)
(二)ORM
对象关系映射:Object (对象,java面向对象) Relational (关系,关系型数据库) Mapping(映射)
(三)Hibernate和JPA的关系
JPA是持久化规范,而Hibernate是这个规范非常好的实现
(四)JPA与JDBC的区别
本质:处理Java对象和关系型数据库表之间的转换
- ▪ JPA运行效率低
▪ JDBC运行效率最高,操作数据库最底层
- ▪ JPA开发效率高,代码简单
▪ JDBC开发效率较低,重复代码太多
- ▪ JPA兼容各种数据库,数据库移植性很强很少的修改(通过配置方言搞定)
▪ JDBC移植数据库很麻烦,改动比较多
- ▪ JPA有内置缓存,性能在一定程度上有优化
▪ JDBC没有提供数据的缓存需要自己实现,性能优化得自己处理
- ▪ JPA面向对象,不能干预sql语句的生成
▪ JDBC面向sql语句操作
二、JPA程序
(一)创建一个web项目
(二)导入jar包
在外层的pom.xml中进行导包
- 导包类型(hibernate核心包,JPA支持包,数据库驱动包,junit测试包)
- JDK1.8插件配置支持
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>com.lty</groupId>
<artifactId>jpa</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>Day1127_JPA</module>
<module>Day1127zy_JPAshopping</module>
</modules>
<!--导包-->
<dependencies>
<!--数据库驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<!--hibernate的核心包-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>
<!--hiberante对于jpa的支持包-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.8.Final</version>
</dependency>
<!--junit测试包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--设置项目JDK版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
(三)配置核心文件
1.生成配置文件
2.调整结构
3.配置persistence.xml
需要的配置属性都可以在此文件里面找到
hibernate-release-4.3.8.Final\hibernate-release-4.3.8.Final\project\etc\hibernate.properties
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
这个配置是要连接数据库(jpa支持连接多个数据库)
persistence-unit:持久化单元(可能有多个,每一个对应一个数据库)
name:取个名称(随便取)
transaction(事务,同生共死)-type(类型)
RESOURCE_LOCAL:本地的事务
JTA: 分布式系统要使用的事务
-->
<persistence-unit name="com.lty.jpa" transaction-type="RESOURCE_LOCAL">
<properties>
<!--配置连接数据库的四个基本属性:驱动、url、用户名、密码-->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql:///jpa"></property>
<property name="hibernate.connection.username" value="root"></property>
<property name="hibernate.connection.password" value="979483"></property>
<!--配置方言(确定使用的哪个数据库)
InnoDB:支持事务,支持外键
MyISAM:不支持事务,不支持外键(属性高)
MySQLDialect:支持以上两种
-->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"></property>
<!--配置自动创建表-->
<property name="hibernate.hbm2ddl.auto" value="update"></property>
<!--显示SQL语句-->
<property name="hibernate.show_sql" value="true"></property>
<!--格式化SQL语句-->
<property name="hibernate.format_sql" value="true"></property>
</properties>
</persistence-unit>
</persistence>
(四)准备domain对象
/**
* @Entity:实体
* @Table :可以确定对应的表;如果没有table,表名默认就是类名
*/
@Entity
@Table(name ="t_employee")
public class Employee {
/**
*@Id:告诉JPA,这是一个主键
*@GeneratedValue:主键生成策略(自增)
*/
@Id
@GeneratedValue
private Long id;
private String name;
private Integer age;
//省略setter,getter
}
(五)基本功能测试
1.生成实体管理工厂
//配置文件中name的值com.lty.jpa
EntityManagerFactory factory = Persistence.createEntityManagerFactory("com.lty.jpa");
2.获取EntityManager核心对象
EntityManager entityManager = factory.createEntityManager();
3.开启事务
entityManager.getTransaction().begin();
4.持久操作CRUD
增删改都需要我们去开启然后提交事务
5.提交事务
entityManager.getTransaction().commit();
6.释放资源
entityManager.close();
三、JPA的CRUD
1.抽取工具类
public class JPAUtil {
private static EntityManagerFactory factory = null;
//加载时运行,只运行一次
static {
try {
factory = Persistence.createEntityManagerFactory("com.lty.jpa");
} catch (Exception e) {
e.printStackTrace();
System.out.println("获取工厂对象出现问题:" + e.getMessage());
}
}
//获取核心对象
public static EntityManager createEntityManager(){
return factory.createEntityManager();
}
}
2.添加
entityManager.persist(employee);
3.修改
entityManager.merge(employee);
4.删除
//先查询一条数据
Employee employee = entityManager.find(Employee.class, id);
//判断是否存在数据,存在再进行删除
if (employee != null){
entityManager.remove(employee);
}
5.查询一条数据
Employee employee = entityManager.find(Employee.class, id);
6.查询所有数据
//写查询语句
1.标准的用法 String jpql = "select o from cn.itsource.jpa.domain.Employee o";
2.String jpql = "select o from Employee o";
3.简写 String jpql = "from Product ";
//创建查询对象
Query query = entityManager.createQuery(jpql);
//根据查询对象获取数据
List list = query.getResultList();
//释放资源
entityManager.close();
return list;
四、建表策略
1.create-drop
测试的时候使用
先删除表 —> 再创建表 —> EntityManagerFactory关闭再删除表
2.create
测试的时候使用
先删除表 —> 再创建表
3.update
- 没有表就创建,有就修改
- 只增不减(不改类型)
- 如果表里面已经有这个属性,如修改属性的长度,不会更新到表里面
- 需要更新这个列先删除表或者删除这个属性对应的列名
- 如果表里面没有属性,映射信息存在,会增加这个列
4.validate
验证功能(只验证domain中写好的属性)
表比映射定义的列要多,不会报错,反之报错
5.none
没有意义,基本不会用
五、核心API
Persistence | 主要用于创建EntityManagerFactory,根据传入的Persistence Unit名称来创建对应的EntityManagerFactory |
---|---|
EntityManagerFactory | EntityManager工厂(负责创建EntityManager对象) |
EntityManager | 实体管理对象 |
EntityTransaction | 事务对象 |
1.Persistence
- 解析相应的核心配置文件
- 创建EntityManagerFactory对象
2.EntityManagerFactory
-
创建 EntityManager对象
-
线程安全的对象1:1:1(一个项目,一个EntityManagerFactory,一个数据库)
-
重量级对象
(1)数据库配置信息(有一个连接池)
(2)二级缓存
(3)预定义的JPQL、SQL语句
(4)所有实体及关系
-
创建和销毁很耗费资源
3.EntityManager
- 完成相应的CRUD
- 线程不安全(一个EntityManager对象只可以由一个线程使用)
- 轻量级对象(一级缓存)
- 创建与销毁不需要耗费太多资源(可以随时创建与销毁)
4.EntityTransaction
- 处理不同数据库不同表的事务管理
- 一个EntityManager只有一个事务对象
- 如果多个系统/多个数据库 -> JTA
- 增删改一定要加事务
六、映射配置细节
1.@Column
/*name:对应的列名
*length:长度
*nullable = true:该字符不能为空
*unique:唯一
*updatable = false:JPA的update语句就不会修改这个字段
*insertable = false:JPA的insert语句就不会添加这个字段
*/
//长度20,数据库名称为username,不能为空,唯一
@Column(name = "username",length = 20,nullable = true,unique = true)
private String name;
2.@Lob
大文本,可以写更多的文字
3.@Transient
临时属性,这一个字段不会同步到数据库
4.@Temporal
//包含年月日时分秒(默认)
@Temporal(TemporalType.TIMESTAMP)
private Date createTime;
//包含年月日
@Temporal(TemporalType.DATE)
private Date birthday;
//包含时分秒
@Temporal(TemporalType.TIME)
private Date time;