什么是ORM
Object relational Mapping 对象关系映射!ORM是一种持久层的开发思想
什么是ORM
1、java开发者不需要关注SQL语句
2、非常方便进行关联关系操作(一对一,一对多,多对多)
3、底层封装JDBC,封装了重复的JDBC操作
JPA是什么
JPA与Hibernate等ORM框架的关系
JPA :是ORM的规范(一套接口)(不干活的)
Hibernate:是一种流行的ORM实现(干活的)
JPA简介
JPA的全称是JAVA Persistence API 即Java 持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成。
JPA通过JDK5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中
二话不说上代码
数据库
CREATE TABLE customer (
cust_id BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
cust_name VARCHAR(32) NOT NULL COMMENT '客户名称(公司名称)',
cust_source VARCHAR(32) DEFAULT NULL COMMENT '客户信息来源',
cust_industry VARCHAR(32) DEFAULT NULL COMMENT '客户所属行业',
cust_level VARCHAR(32) DEFAULT NULL COMMENT '客户级别',
cust_address VARCHAR(128) DEFAULT NULL COMMENT '客户联系地址',
cust_phone VARCHAR(64) DEFAULT NULL COMMENT '客户联系电话',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
pom.xml
<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.jsonString</groupId>
<artifactId>springdatajpa_demo01_01_jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.hibernate.version>5.0.7.Final</project.hibernate.version>
</properties>
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- hibernate对jpa的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- log日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Mysql and MariaDB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
</project>
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 让Hibernate维护表结构 -->
<!-- persistence-unit:持久化单元,类似于数据源
name:单元名称,一个项目必须唯一的
transaction-type:事务类型
JTA:分布式事务(多个数据库的操作)
RESOURCE_LOCAL:本地事务(只有一个数据库的操作)
-->
<persistence-unit name="jsonStringJpa" transaction-type="RESOURCE_LOCAL" >
<!-- provider:Jpa的具体提供商(ORM实现) -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--数据库连接属性-->
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1/springdatajpa_2021?characterEncoding=utf8"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="albee1222"/>
<!-- 查看hibernate生成的sql语句方便调试 -->
<property name="hibernate.show_sql" value="true"/>
<!--让hibernate维护表结构
create:每次先删除表,再创建表
update:有表,判断表有无改变,如果有,修改表;如果没有,什么也不干
nont:什么都不干
-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
工具类
package com.jsonString.util;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* Jpa工具类
* @author 16427
*
*/
public class JpaUtil {
//保证一个项目一个工厂
private static EntityManagerFactory factory=null;
/**
* 创建工厂,只创建1次
*/
static {
factory=Persistence.createEntityManagerFactory("jsonStringJpa");
}
/**
* 每次获取EntityManager来使用
*/
public static EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
实体类
package com.jsonString.pojo;
import java.io.Serializable;
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="customer") //映射表
public class Customer implements Serializable {
@Id //映射主键
//此种策略适用于有数据库自动增长的策略:auto_increment:mysql数据库(Orcle没有自增长策略的)
//@GeneratedValue(strategy=GenerationType.IDENTITY) //主键生成策略.IDENTITY:利用数据库自增策略
//@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="aaaa")//序列机制数据库:oracle
//@GeneratedValue(strategy=GenerationType.TABLE)//适用于没有自动增长策略和序列机制的数据库 性能不好
@Column(name="cust_id") //映射字段
private Long custId;
@Column(name="cust_name")
private String custName;
@Column(name="cust_source")
private String custSource;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_phone")
private String custPhone;
//省略get和set
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
@Override
public String toString() {
return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource + ", custLevel="
+ custLevel + ", custIndustry=" + custIndustry + ", custAddress=" + custAddress + ", custPhone="
+ custPhone + "]";
}
}
package com.jsonString.pojo;
public class CustomerVo {
private String custLevel;
private Long custCount;
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public Long getCustCount() {
return custCount;
}
public void setCustCount(Long custCount) {
this.custCount = custCount;
}
@Override
public String toString() {
return "CustomerVo [custLevel=" + custLevel + ", custCount=" + custCount + "]";
}
public CustomerVo(String custLevel, Long custCount) {
super();
this.custLevel = custLevel;
this.custCount = custCount;
}
public CustomerVo() {
super();
}
}
单元测试
package com.jsonString.test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.junit.Test;
import com.jsonString.pojo.Customer;
import com.jsonString.util.JpaUtil;
public class Demo1 {
@Test
public void test1() {//注意:使用该方法一定要有主键策略
//1.创建实体管理器工厂(类似于mybatis的SqlSessionFactory)
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jsonStringJpa");
//2.创建实体管理器(类似于mybatis的SqlSession)
EntityManager em=factory.createEntityManager();
//3.获取事务对象(增删改操作需要事务,查询不需要)
EntityTransaction tx=em.getTransaction();
//4.开启事务
tx.begin();
//5.执行操作
Customer cust=new Customer();
cust.setCustName("jsonString0642");
cust.setCustIndustry("IT");
cust.setCustLevel("VIP");
em.persist(cust);
//6.提交事务
tx.commit();
//7.释放资源
em.close();
factory.close();
}
@Test
public void test() {
//1、加载配置文件创建实体类管理器工厂
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jsonStringJpa");
//2、根据实体类管理器工厂创建实体类管理器
EntityManager em=factory.createEntityManager();
//3、获取事务对象
EntityTransaction tx=em.getTransaction();
//4、开启事务
tx.begin();
//5、保存客户实体
Customer c=new Customer();
c.setCustId(3L);//没有主键策略要自己指定主键
c.setCustName("jsonString没有主键策略");
c.setCustLevel("白金VIP");
em.persist(c);
//6、提交事务
tx.commit();
//7、释放资源
em.close();
factory.close();
}
/**
* 使用JpaUtil工具类
*/
@Test
public void test2() {
//1.从工具获取EntityManager
EntityManager em=JpaUtil.getEntityManager();
//2.获取事务对象(增删改操作需要事务,查询不需要事务)
EntityTransaction tx=em.getTransaction();
try {
//3.开启事务
tx.begin();
//4.执行操作
Customer cust=new Customer();
cust.setCustId(15L);
cust.setCustName("jsonStringJpaUtil");
cust.setCustIndustry("工厂");
cust.setCustLevel("VIP");
em.persist(cust);
//5.提交事务
tx.commit();
}catch(Exception e) {
e.printStackTrace();
//6.事务回滚
tx.rollback();
}finally {
//7.释放资源
em.close();
}
}
/**
* 查询一个(不需要事务)
*/
@Test
public void test3() {
EntityManager em=JpaUtil.getEntityManager();
try {
//find();立刻加载方式
//Customer cust=em.find(Customer.class, 11L);
//getReference();延迟加载方式。什么是延迟加载?没有用到就不查询数据库,用到就查询数据库
Customer cust=em.getReference(Customer.class, 11L);
System.out.println(cust);
}catch(Exception e) {
e.printStackTrace();
}finally {
//7.释放资源
em.close();
}
}
/**
* 修改
*/
@Test
public void test4() {
EntityManager em=JpaUtil.getEntityManager();
EntityTransaction tx=em.getTransaction();
try {
tx.begin();
/**
* 1)直接修改(项目中大部分都采用这种方式)
* 2)先查询,再修改
*/
//1直接修改
/*Customer cust=new Customer();
cust.setCustId(11L);
cust.setCustName("JsonString修改");*/
//2.先查询,再修改
Customer cust=em.find(Customer.class, 11L);
cust.setCustName("JsonString先查询再修改");
em.merge(cust);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
em.close();
}
}
/**
* 删除
*/
@Test
public void test5() {
EntityManager em=JpaUtil.getEntityManager();
EntityTransaction tx=em.getTransaction();
try {
tx.begin();
//必须先查询再删除
Customer cust=em.find(Customer.class, 11L);
//Customer cust=new Customer();
//cust.setCustId(11L);
em.remove(cust);
tx.commit();
}catch(Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
em.close();
}
}
}
package com.jsonString.test;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.junit.Test;
import com.jsonString.pojo.Customer;
import com.jsonString.pojo.CustomerVo;
import com.jsonString.util.JpaUtil;
/**
* 演示Jpa的查询操作
* @author 16427
*
*/
public class Demo2 {
//全部数据查询
@Test
public void test2() {
EntityManager em=JpaUtil.getEntityManager();
try {
//1.创建Query对象,进行JPQL
//String jpql="select c from Customer c";//完整的写法
String jpql="from Customer";//简化写法
Query query=em.createQuery(jpql);
//2.取出并封装数据
List<Customer> list=query.getResultList();
for(Customer cust:list) {
System.out.println(cust);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
//7.释放资源
em.close();
}
}
//分页查询数据
@Test
public void test3() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="from Customer";//简化版本
Query query=em.createQuery(jpql);
//模拟页面参数
int pageNum=2;
int pageSize=2;
//获取结果之前,设置分页参数
query.setFirstResult((pageNum-1)*pageSize);//查询起始行号,从零开始
query.setMaxResults(pageSize);//页面大小
List<Customer> list=query.getResultList();
for(Customer cust:list) {
System.out.println(cust);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 条件查询数据 -- 精准查询
*/
@Test
public void test4() {
EntityManager em=JpaUtil.getEntityManager();
try {
//第一种占位方式:名称
//String jpql="from Customer where custName=:abc";
//第二种占位方式:?序号(推荐使用)
String jpql="from Customer where custName=?1 and custLevel = ?2";
Query query= em.createQuery(jpql);
//设置参数
//query.setParameter("abc", "jsonString没有主键策略");//第一种占位方式:名称
query.setParameter(1, "jsonStringJpaUtil");
query.setParameter(2, "VIP");
List<Customer> list=query.getResultList();
for(Customer cust:list) {
System.out.println(cust);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 条件查询数据--模糊查询
*
*/
@Test
public void test5() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="from Customer where custName like ?1";
Query query=em.createQuery(jpql);
query.setParameter(1, "%Json%");
List<Customer> list=query.getResultList();
for(Customer cust:list) {
System.out.println(cust);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 排序查询数据
*/
@Test
public void test6() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="from Customer order by custId desc";
Query query=em.createQuery(jpql);
List<Customer> list=query.getResultList();
for(Customer cust:list) {
System.out.println(cust);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 统计查询数据
*/
@Test
public void test7() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="select count(1) from Customer";
Query query=em.createQuery(jpql);
//注意通常统计结果只有一个值
Object result =query.getSingleResult();
System.out.println(result);
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 分组统计查询数据-- 对象数据返回
*/
@Test
public void test8() {
EntityManager em=JpaUtil.getEntityManager();
try {
/**
* SQL
* 需求:统计每种客户级别的人数
* SELECT cust_level,COUNT(cust_id) FROM customer GROUP BY cust_level
* */
String jpql="select custLevel,count(1) from Customer group by custLevel";
Query query=em.createQuery(jpql);
//分组查询的结果有多个,返回对象数组的list集合
List<Object[]> list=query.getResultList();
for(Object[] array:list) {
for(Object obj:array) {
System.out.println(obj+"\t");
}
System.out.println();
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
/**
* 分组统计查询数据-- JavaBean对象返回
*
*/
@Test
public void test9() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="select new com.jsonString.pojo.CustomerVo(custLevel,count(custId)) from Customer group by custLevel";
Query query =em.createQuery(jpql);
//分组查询的结果多个,返回对象数组List集合
List<CustomerVo> list=query.getResultList();
for(CustomerVo vo:list) {
System.out.println(vo);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
@Test
public void test10() {
EntityManager em=JpaUtil.getEntityManager();
try {
String jpql="select custLevel,count(1) from Customer group by custLevel";
Query query=em.createQuery(jpql);
List<Object[]> list=query.getResultList();
for(Object[] array:list) {
for(Object obj:array) {
System.out.println(obj+"\t");
}
System.out.println();
}
}catch(Exception e) {
e.printStackTrace();
}finally {
em.close();
}
}
}
JPA的核心API介绍
1、Persistence(一般)
作用:加载persistence.xml配置文件创建实体类管理器工厂(加载完配置文件到内存然后进行后续操作)
方法:createEntityManagerFactory(“持久化单元名称”)
2、EntityManagerFactory(比较重要)
作用:用于生产实体类管理器
方法: createEntityManager();
close();
细节: 1、这个类是一个重量级的类,它维护了非常多的信息:如全字段插入、全字段更新、根据id查询、根据id删除等这一系列通用的sql语句 。(如根据id以外某个字段查询的这些不通用的sql语句则交给EntityManager管理)
2、这个类是线程安全的
使用原则:一个项目只有一个这个对象
3、EntityManager(非常重要)
作用:获取事务对象,与数据库的交互都是他来完成
方法: persist() 保存
merge()更新
remove()删除
getReference()||findOne()查询一个对象
细节:1、由于工厂(EntityManagerFactory) 已经维护了非常多的信息,所以这个类维护信息就少了、维护了参数而已,它就是轻量级的对象
2、它是线程不安全的
使用原则:
一次请求,用的都是同一个 EntityManager对象