JPA学习总结
JPA简介
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA包含的技术
ORM映射元数据
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
API
用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
引入相关jar包
pom.xml
<?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.pec</groupId>
<artifactId>jpa_learn01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.hibernate.version>5.4.2.Final</project.hibernate.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--hibernate对jpa支持的依赖 -->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
在resources目录下创建一个META-INF,在该目录下创建persistence.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--配置persistence-unit节点
持久化单元
name;持久化单元名称
transaction-type:事务管理的方式
JPA:多个数据源,多个数据库,主要是实现分布式数据库的
RESOURCE_LOCAL:单个数据源,单个数据库,本地实现的
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--配置JPA的实现方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--配置JPA的实现方的配置信息(可选配置) -->
<properties>
<!--数据库信息 -->
<!--用户名:
密码:
驱动:
数据库地址:-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="Luoguibin6!"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa?serverTimezone=UTC"/>
<!--配置实现方(hibernate)的配置信息 -->
<!--显示sql false|true
自动创建数据库表的策略:hibernate.hbm2ddl.auto
create:自动创建表,不管数据库是否有表,都会创建表
update:如果数据库中没有表,再创建表,如果有表,则不会再创建表
none:不管有无表,都不会创建表,如果不进行配置,默认状态下就会采用这种方式
-->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!--<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>-->
</properties>
</persistence-unit>
</persistence>
封装JPA操作工具类
package com.pec.oa.utils;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JPAUtil {
private static EntityManagerFactory entityManagerFactory;
//加载持久化数据单元文件,生成一个实体管理器工厂对象
static {
entityManagerFactory=Persistence.createEntityManagerFactory("myJpa");
}
public static EntityManager getEntityManager(){
return entityManagerFactory.createEntityManager();
}
}
配置数据库表与实体类映射
package com.pec.oa.pojo;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* 配置实体类和数据库表的映射关系
* 配置实体类中属性和数据库表中字段的映射关系
* @Entity:声明实体类
* @Table:配置实体类和表的映射关系
* name:配置数据库表的名称
*/
@Entity
@Table(name = "u_user")
public class User implements Serializable {
@Id //配置主键
@GeneratedValue(strategy =GenerationType.IDENTITY )//配置主键生成的策略,默认是auto
//IDENTITY:自动增长,前提是底层数据库必须支持自动增长,mysql
//SEQUENCE:序列,底层数据库必须支持序列,Oracle
//Table:JPA提供的一直机制,通过一种数据库表的形式的主键自增
//auto:由程序自动的选择一种主键生成策略。
@Column(name = "u_id")
private Integer uId;
@Column(name = "u_username")
private String uUsername;
@Column(name = "u_password")
private String uPassword;
@Column(name = "u_sex")
private String uSex;
@Column(name = "u_age")
private Integer uAge;
@Column(name = "u_registryDate")
private Timestamp uRegistryDate;
public User() {
}
public Integer getuId() {
return uId;
}
public void setuId(Integer uId) {
this.uId = uId;
}
public String getuUsername() {
return uUsername;
}
public void setuUsername(String uUsername) {
this.uUsername = uUsername;
}
public String getuPassword() {
return uPassword;
}
public void setuPassword(String uPassword) {
this.uPassword = uPassword;
}
public String getuSex() {
return uSex;
}
public void setuSex(String uSex) {
this.uSex = uSex;
}
public Integer getuAge() {
return uAge;
}
public void setuAge(Integer uAge) {
this.uAge = uAge;
}
public Timestamp getuRegistryDate() {
return uRegistryDate;
}
public void setuRegistryDate(Timestamp uRegistryDate) {
this.uRegistryDate = uRegistryDate;
}
@Override
public String toString() {
return "User{" +
"uId=" + uId +
", uUsername='" + uUsername + '\'' +
", uPassword='" + uPassword + '\'' +
", uSex='" + uSex + '\'' +
", uAge=" + uAge +
", uRegistryDate=" + uRegistryDate +
'}';
}
}
创建测试类完成增删查改操作
package com.pec.oa.test;
import com.pec.oa.pojo.User;
import com.pec.oa.utils.JPAUtil;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import java.sql.Timestamp;
public class TestJpa {
/**
* 测试JPA的插入操作
* 加载配置文件创建实体管理类工厂 EntityManagerFactory对象(线程安全)
* 通过实体管理类工厂创建实体管理类
*获取事务对象,加载事务
*完成增删改查此操作
*提交事务
* 释放资源
* 实体管理器对象EntityManager的方法:
* beginTransaction():创建一个事务对象
* persist():保存
* merge():更新
* remove():删除
* find/getReference:根据id查询
* Transaction对象:事务
* begin:开启事务
* commit:提交事务
* rollback:回滚
*/
@Test
//增加数据
public void test01(){
//使用工具类创建实体对象
EntityManager entityManager =JPAUtil.getEntityManager();
//获取事务对象
EntityTransaction tx =entityManager.getTransaction();
//开启事务
tx.begin();
User user =new User();
user.setuUsername("张三");
user.setuPassword("123456");
user.setuRegistryDate(new Timestamp(System.currentTimeMillis()));
entityManager.persist(user);
//提交
tx.commit();
//释放资源
entityManager.close();
//managerFactory.close();
}
/**
* 查询数据
* find(操作对象实例【反射】,id),通过id查询
* 当调用find方法的时候就会进行sql查询(立即查询),当调用find方法的时候就会查询
*/
@Test
public void test02(){
//1.创建实体类对象管理器
EntityManager entityManager =JPAUtil.getEntityManager();
//2.进行查询操作,查询不属于事务性操作
User user=entityManager.find(User.class,1);
System.out.println(user);
entityManager.close();
}
/**
* 查询数据
* 使用getReference()方法使用同样的参数,但是过程不一样
* getReference()方法查询得到的是一个代理对象,只有当这个对象被引用的时候才会去查询。
* 类似于(延时加载)懒加载
*/
@Test
public void test03(){
//1.创建实体类对象管理器
EntityManager entityManager =JPAUtil.getEntityManager();
//2.进行查询操作,查询不属于事务性操作
User user=entityManager.getReference(User.class,1);
System.out.println(user);
entityManager.close();
}
/**
* 删除操作
*/
@Test
public void test04() {
EntityManager entityManager =JPAUtil.getEntityManager();
//获取事务对象
EntityTransaction tx =entityManager.getTransaction();
//开启事务
tx.begin();
//完成增删改查操作
User user =entityManager.find(User.class,1);
entityManager.remove(user);
//提交
tx.commit();
//释放资源
entityManager.close();
}
/**
* 更新操作
* merge()方法
*/
@Test
public void test05() {
EntityManager entityManager =JPAUtil.getEntityManager();
//获取事务对象
EntityTransaction tx =entityManager.getTransaction();
//开启事务
tx.begin();
//完成增删改查操作
User user =entityManager.find(User.class,3);
user.setuUsername("李四");
entityManager.merge(user);
//提交
tx.commit();
//释放资源
entityManager.close();
}
}
测试使用Jpql进行操作
package com.pec.oa.test;
import com.pec.oa.utils.JPAUtil;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class TestJpql {
/**
* 查询全部
* 创建query对象
* 1.根据jpql创建查询对象
* 2.
*/
@Test
public void test01(){
EntityManager entityManager =JPAUtil.getEntityManager();
String jpql="from com.pec.pojo.User order by id desc";
Query query =entityManager.createQuery(jpql);
List list =query.getResultList();
for(Object o:list){
System.out.println(o);
}
}
/**
* 统计个数count(实体类的属性)
* getSingleResult()获取单个结果集
*/
@Test
public void test02(){
EntityManager entityManager =JPAUtil.getEntityManager();
String jpql1="select count(id) from com.pec.pojo.User";
Query query =entityManager.createQuery(jpql1);
Object o = query.getSingleResult();
System.out.println(o);
}
/**
* 分页,这个分页默认的是先经过全表查询之后才分页的,所以并不能减轻数据库的压力
* jpql:from User
* 分页参数:
* setFirstResult:起始位置,不包括起始位置
* setMaxResult:每页展示的最大条数。
* 观察jpql语句可以看到内部还是使用limit关键字进行查询的,从0开始查询不包括0,所以只用带一个参数2
*/
@Test
public void test03(){
EntityManager entityManager =JPAUtil.getEntityManager();
String jpql="from User";
Query query =entityManager.createQuery(jpql);
query.setFirstResult(0);
query.setMaxResults(2);
List list =query.getResultList();
for(Object o:list){
System.out.println(o);
}
}
/**
* 条件查询,hibernate4.1之后对占位符做了修改,所以在JPA中可以使用
* from User where uUsername like ?0,0代表这个占位符的索引
*/
@Test
public void test04(){
EntityManager entityManager =JPAUtil.getEntityManager();
String jpql="from com.pec.pojo.User where uUsername like ?1";
Query query =entityManager.createQuery(jpql);
query.setParameter(1,"张%");
List list =query.getResultList();
for(Object o:list){
System.out.println(o);
}
}
}