一、ORM概述
1、ORM的概念
ORM是软件开发的一种思想,主要针对持久层
ORM描述的对象关系映射
O --> Object --> 对象
R --> Relational --> 关系表
M --> Mapping --> 映射
2、ORM的作用
1、让开发人员不用关注SQL语句
2、操作类就是操作表
3、隐藏不同数据库的差异
3、实现了ORM思想的框架称为ORM框架
二、Hibernate概述和JPA概述
1、Hibernate的概述【实现】
Hibernate一种开源、流行的ORM框架。底层封装JDBC,是ORM思想的一种实现
2、JPA的概述【接口】
JPA是由SUN公司提出的这对ORM框架的规范。 内部是接口。
众多ORM实现厂商针对JPA里的接口进行实现。
开发人员面向JPA接口进行开发,只需要了解一套API。统一了ORM框架的语法。
3、Hibernate和JPA的关系
1)、Hibernate和JPA是实现和接口的关系。JPA是接口,Hibernate是实现
2)、Hibernate的作用:简化JDBC操作、让开发人员不关注SQL语句
3)、JPA的作用:统一ORM语法,实现ORM框架无缝切换。多态思想
4、总结
开发人员面向JPA编程,ORM实现厂商实现JPA接口。
面向JPA的开发就是面向接口开发。
三、JPA入门,把数据写入数据库
1、创建数据库和表
/*创建客户表*/
CREATE TABLE cst_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;
2、搭建开发环境
1)创建工程,引入依赖
注意:JPA是规范,无法操作数据库,需要引入Hibernate对JPA的实现包
<!-- hibernate 对 jpa 的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.7</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.0.7</version>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- log 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2)创建持久化类
一个类如果与数据中的某个表有映射关系,这个类就是持久化类
/**
* * 所有的注解都是使用 JPA 的规范提供的注解,
* * 所以在导入注解包的时候,一定要导入 javax.persistence 下的
*/
@Entity //声明实体类
@Table(name="cst_customer") //建立实体类和表的映射关系
public class Customer {
//声明当前私有属性为主键
@Id
//配置主键的生成策略,IDENTITY是数据库的自增
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="cust_id") //指定和表中 cust_id 字段的映射关系
private Long custId;
@Column(name="cust_name") //指定和表中 cust_name 字段的映射关系
private String custName;
@Column(name="cust_source")//指定和表中 cust_source 字段的映射关系
private String custSource;
@Column(name="cust_industry")//指定和表中 cust_industry 字段的映射关系
private String custIndustry;
@Column(name="cust_level")//指定和表中 cust_level 字段的映射关系
private String custLevel;
@Column(name="cust_address")//指定和表中 cust_address 字段的映射关系
private String custAddress;
@Column(name="cust_phone")//指定和表中 cust_phone 字段的映射关系
private String custPhone;
//get() set()方法略。。。
}
常见注解说明:
@Entity :指定当前类是实体类。
@Table :指定实体类和表之间的对应关系。
属性:
name:指定数据库表的名称
@Id :指定当前字段是主键。
@GeneratedValue :指定主键的生成方式。。
属性:
strategy :指定主键生成策略。
generator:指定引用 hibernate 中声明的主键策略
@Column :指定实体类属性和数据库表之间的对应关系
属性:
name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的 DDL
secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名
3)创建JPA核心配置文件
注意:在 maven 工程的 resources 路径下创建一个名为 META-INF 的文件夹,在此文件夹下创建一个名为
persistence.xml 的配置文件。META-INF 文件夹名称不能修改。 persistence.xml 文件名称不能改
<?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">
<!--persistence-unit 配置持久化单元 可以配置多个-->
<!--name:持久化单元名称
transaction-type:事务类型
RESOURCE_LOCAL:本地事务管理
JTA:分布式事务管理 -->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--配置 JPA 规范的服务提供商 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--配置持久化类-->
<class>com.itheima.po.Customer</class>
<properties>
<!-- 数据库驱动 -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<!-- 数据库地址 -->
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost:3306/day01" />
<!-- 数据库用户名 -->
<property name="javax.persistence.jdbc.user" value="root" />
<!-- 数据库密码 -->
<property name="javax.persistence.jdbc.password" value="123456" />
<!--jpa 提供者的可选配置:我们的 JPA 规范的提供者为 hibernate,所以 jpa 的核心配
置中兼容 hibernate 的配 -->
<!-- 显示SQL -->
<property name="hibernate.show_sql" value="true" />
<!-- 格式化SQL -->
<property name="hibernate.format_sql" value="true" />
<!-- 自动创建表 -->
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
4)编写代码
@Test
public void testSave() {
/**
* 创建实体管理类工厂,使用 Persistence 的静态方法获取
* 其中传递的参数为持久化单元名称,需要 jpa 配置文件中指定
*/
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//创建实体管理类
EntityManager em = factory.createEntityManager();
//获取事务对象
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
//创建要操作的对象
Customer customer = new Customer();
c.setCustName("传智播客");
//保存操作
em.persist(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
四、JPA的API介绍
Persistence //工具类,用来创建EntityManagerFactory
EntityManagerFactory //工厂类,用来创建EntityManager
EntityManager //核心类,封装操作数据库的方法
EntityTransaction //事务对象
五、抽取工具类
public final class JPAUtil {
// JPA 的实体管理器工厂:相当于 Hibernate 的 SessionFactory
private static EntityManagerFactory em;
// 使用静态代码块赋值
static {
// 注意:该方法参数必须和 persistence.xml 中 persistence-unit 标签 name 属性取值一致
em = Persistence.createEntityManagerFactory("myPersistUnit");
}
/**
* 使用管理器工厂生产一个管理器对象
* @return
*/
public static EntityManager getEntityManager() {
return em.createEntityManager();
}
}
六、JPA的CRUD
1、查询
@Test
public void testFindOne() {
// 定义对象
EntityManager em = JPAUtil.getEntityManager();
EntityTransaction tx = em.getTransaction();
// 开启事务
tx.begin();
// 执行操作
Customer customer = em.find(Customer.class, 1L);
// 提交事务
tx.commit();
System.out.println(customer.getCustName()); // 输出查询对象
// 释放资源
em.close();
}
2、修改
@Test
public void testMerge(){
//定义对象
EntityManager em=JPAUtil.getEntityManager();
EntityTransaction tx=em.getTransaction();
//开启事务
tx.begin();
//执行操作
Customer customer = em.find(Customer.class, 1L);
customer.setCustName("传智播客-黑马程序员");
em.merge(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
//注意:修改操作要先查询,然后用查询出来的对象进行修改操作
3、删除
@Test
public void testRemove(){
//定义对象
EntityManager em=JPAUtil.getEntityManager();
EntityTransaction tx=em.getTransaction();
//开启事务
tx.begin();
//执行操作
Customer customer = em.find(Customer.class, 1L);
em.remove(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
4、根据id查询的两种方式
public void testGetOne() {
EntityManager em = JPAUtil.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//find 立即加载,立即发送SQL进行查询,返回的是真实对象
Customer customer1 = em.find(Customer.class, 2L);
System.out.println(customer1);
//getReference 延迟加载,不会立即发送SQL查询,返回的是代理对象
//在Debug模式下可以看到 对象是带着$符号,就是代理对象
Customer customer2 = em.getReference(Customer.class, 2L);
System.out.println(customer2);
tx.commit();
em.close();
}
七、JPA的JPQL查询
JPQL 全称 Java Persistence Query Language,与原生 SQL 语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的列名
1、查询全部
public void testFindAll() {
EntityManager em = JPAUtil.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 创建 query 对象
String jpql = "from Customer";
Query query = em.createQuery(jpql);
// 查询并得到返回结果
List<Customer> list = query.getResultList(); // 得到集合返回类型
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
em.close();
}
2、条件查询
public void testFindAll() {
EntityManager em = JPAUtil.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 创建 query 对象
String jpql = "from Customer where custName like ? and custId=?";
Query query = em.createQuery(jpql);
//对占位符赋值, 从 1 开始
query.setParameter(1, "传智播客%");
query.setParameter(2,2L);
// 查询并得到返回结果
List<Customer> list = query.getResultList(); // 得到集合返回类型
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
em.close();
}
3、排序查询
public void testFindAll() {
EntityManager em = JPAUtil.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 创建 query 对象
String jpql = "from Customer order by custId desc";
Query query = em.createQuery(jpql);
// 查询并得到返回结果
List<Customer> list = query.getResultList(); // 得到集合返回类型
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
em.close();
}
4、分页查询
public void testFindAll() {
EntityManager em = JPAUtil.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 创建 query 对象
String jpql = "from Customer";
Query query = em.createQuery(jpql);
//起始索引
query.setFirstResult(0);
//每页显示条数
query.setMaxResults(2)
// 查询并得到返回结果
List<Customer> list = query.getResultList(); // 得到集合返回类型
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
em.close();
}