文章目录
一 学习ORM思想启发
- 1 建立实体类与表中的关系
- 2 建立实体类中属性和表中字段关系
二 学习ORM思想
2.1 orm思想
主要目的:
操作实体类就相当于操作数据库表
建立两个映射关系:
实体类和表的映射关系
实体类中属性和表中字段的映射关系
不再重点关注:sql语句
实现了ORM思想的框架:mybatis,hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,
它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,
自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
2.2 hibernate框架介绍
Hibernate是一个开放源代码的对象关系映射框架,
它对JDBC进行了非常轻量级的对象封装,
它将POJO与数据库表建立映射关系,是一个全自动的orm框架
2.3 JPA规范
jpa规范,实现jpa规范,内部是由接口和抽象类组成
附加:PA与hibernate的关系
JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。
JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。
三 jpa的基本操作
3.1 创建客户表 (客户是一家公司)
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;
3.2 创建maven工程 导入坐标
<?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>cn.itcast</groupId>
<artifactId>jpa-day2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.6</mysql.version>
</properties>
<dependencies>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring对orm框架的支持包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<!-- hibernate beg -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->
<!-- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- c3p0 end -->
<!-- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- spring data jpa 的坐标-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- el end -->
</dependencies>
</project>
3.3 需要配置jpa核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--需要配置persistence-unit节点
持久化单元:
name:持久化单元名称
transaction-type:事务管理的方式
JTA:分布式事务管理
RESOURCE_LOCAL:本地事务管理
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--jpa的实现方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--可选配置:配置jpa实现方的配置信息-->
<properties>
<!-- 数据库信息
用户名,javax.persistence.jdbc.user
密码, javax.persistence.jdbc.password
驱动, javax.persistence.jdbc.driver
数据库地址 javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///springssm"/>
<!--配置jpa实现方(hibernate)的配置信息
显示sql : false|true
自动创建数据库表 : hibernate.hbm2ddl.auto
create : 程序运行时创建数据库表(如果有表,先删除表再创建)
update :程序运行时创建表(如果有表,不会创建表)
none :不会创建表
-->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
3 .4配置客户实体类和表,类中属性和表中字段映射关系
/**
* 客户的实体类
* 配置映射关系
*
*
* 1.实体类和表的映射关系
* @Entity:声明实体类
* @Table : 配置实体类和表的映射关系
* name : 配置数据库表的名称
* 2.实体类中属性和表中字段的映射关系
*
*
*/
@Entity
@Table(name = "cst_customer")
public class Customer {
/**
* @Id:声明主键的配置
* @GeneratedValue:配置主键的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底层数据库必须支持序列
* GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
* @Column:配置属性和字段的映射关系
* name:数据库表中字段的名称
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@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_phone")
private String custPhone;//客户的联系方式
@Column(name="cust_address")
private String custAddress;//客户地址
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 getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custLevel='" + custLevel + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custPhone='" + custPhone + '\'' +
", custAddress='" + custAddress + '\'' +
'}';
}
}
3.5 保存客户信息并配置静态工厂
1.加载配置文件创建实体管理器工厂
Persisitence:静态方法(根据持久化单元名称创建实体管理器工厂)
createEntityMnagerFactory(持久化单元名称)
作用:创建实体管理器工厂
2.根据实体管理器工厂,创建实体管理器
EntityManagerFactory :获取EntityManager对象
方法:createEntityManager
* 内部维护的很多的内容
内部维护了数据库信息,
维护了缓存信息
维护了所有的实体管理器对象
再创建EntityManagerFactory的过程中会根据配置创建数据库表
* EntityManagerFactory的创建过程比较浪费资源
特点:线程安全的对象
多个线程访问同一个EntityManagerFactory不会有线程安全问题
* 如何解决EntityManagerFactory的创建过程浪费资源(耗时)的问题?
思路:创建一个公共的EntityManagerFactory的对象
* 静态代码块的形式创建EntityManagerFactory
* 解决实体管理器工厂的浪费资源和耗时问题
* 通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象
* 第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用方法创建一个EntityManager对象
* 第二次方法getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象
public class JpaUtils {
private static EntityManagerFactory factory;
static {
//1.加载配置文件,创建entityManagerFactory
factory = Persistence.createEntityManagerFactory("myJpa");
}
/**
* 获取EntityManager对象
*/
public static EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
3.6 测试并校验结果
步骤关键字段总结
创建事务对象,开启事务
Transaction 对象 : 事务
begin:开启事务
commit:提交事务
rollback:回滚
EntityManager对象:实体类管理器
beginTransaction : 创建事务对象
presist : 保存
merge : 更新
remove : 删除
find/getRefrence : 根据id查询
注意事项:
根据id查询客户
1.使用find方法查询:
查询的对象就是当前客户对象本身
在调用find方法的时候,就会发送sql语句查询数据库
2.getReference方法
获取的对象是一个动态代理对象
调用getReference方法不会立即发送sql语句查询数据库
当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
测试代码:
public class JpaTest {
/**
* 测试jpa的保存
* 案例:保存一个客户到数据库中
* Jpa的操作步骤
* 1.加载配置文件创建工厂(实体管理器工厂)对象
* 2.通过实体管理器工厂获取实体管理器
* 3.获取事务对象,开启事务
* 4.完成增删改查操作
* 5.提交事务(回滚事务)
* 6.释放资源
*/
@Test
public void testSave() {
// //1.加载配置文件创建工厂(实体管理器工厂)对象
// EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
// //2.通过实体管理器工厂获取实体管理器
// EntityManager em = factory.createEntityManager();
EntityManager em = JpaUtils.getEntityManager();
//3.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction(); //获取事务对象
tx.begin();//开启事务
//4.完成增删改查操作:保存一个客户到数据库中
//保存,
for (int i = 0; i < 4; i++) {
Customer customer = new Customer();
customer.setCustName("传智播客"+i);
customer.setCustIndustry("教育"+i);
em.persist(customer); //保存操作
}
//5.提交事务
tx.commit();
//6.释放资源
em.close();
// factory.close();
}
/**
* 根据id查询客户
* 使用find方法查询:
* 1.查询的对象就是当前客户对象本身
* 2.在调用find方法的时候,就会发送sql语句查询数据库
*
* 立即加载
*
*
*/
@Test
public void testFind() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
//3.增删改查 -- 根据id查询客户
/**
* find : 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值
*/
Customer customer = entityManager.find(Customer.class, 1l);
// System.out.print(customer);
//4.提交事务
tx.commit();
//5.释放资源
entityManager.close();
}
/**
* 根据id查询客户
* getReference方法
* 1.获取的对象是一个动态代理对象
* 2.调用getReference方法不会立即发送sql语句查询数据库
* * 当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
*
* 延迟加载(懒加载)
* * 得到的是一个动态代理对象
* * 什么时候用,什么使用才会查询
*/
@Test
public void testReference() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
//3.增删改查 -- 根据id查询客户
/**
* getReference : 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值
*/
Customer customer = entityManager.getReference(Customer.class, 1l);
System.out.print(customer);
//4.提交事务
tx.commit();
//5.释放资源
entityManager.close();
}
/**
* 删除客户的案例
*
*/
@Test
public void testRemove() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
//3.增删改查 -- 删除客户
//i 根据id查询客户
Customer customer = entityManager.find(Customer.class,1l);
//ii 调用remove方法完成删除操作
entityManager.remove(customer);
//4.提交事务
tx.commit();
//5.释放资源
entityManager.close();
}
/**
* 更新客户的操作
* merge(Object)
*/
@Test
public void testUpdate() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
//3.增删改查 -- 更新操作
//i 查询客户
Customer customer = entityManager.find(Customer.class,1l);
//ii 更新客户
customer.setCustIndustry("it教育");
entityManager.merge(customer);
//4.提交事务
tx.commit();
//5.释放资源
entityManager.close();
}
}
四 jpql基本操作
JPQL全称Java Persistence Query Language
基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。
其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。
测试jqpl查询
**
* 测试jqpl查询
*/
public class JpqlTest {
/**
* 查询全部
* jqpl:from cn.itcast.domain.Customer
* sql:SELECT * FROM cst_customer
*/
@Test
public void testFindAll() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
String jpql = "from Customer ";
Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象
//发送查询,并封装结果集
List list = query.getResultList();
for (Object obj : list) {
System.out.print(obj+"\n");
}
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
/**
* 排序查询: 倒序查询全部客户(根据id倒序)
* sql:SELECT * FROM cst_customer ORDER BY cust_id DESC
* jpql:from Customer order by custId desc
*
* 进行jpql查询
* 1.创建query查询对象
* 2.对参数进行赋值
* 3.查询,并得到返回结果
*/
@Test
public void testOrders() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
String jpql = "from Customer order by custId desc";
Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象
//发送查询,并封装结果集
List list = query.getResultList();
for (Object obj : list) {
System.out.println(obj);
}
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
/**
* 使用jpql查询,统计客户的总数
* sql:SELECT COUNT(cust_id) FROM cst_customer
* jpql:select count(custId) from Customer
*/
@Test
public void testCount() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
//i.根据jpql语句创建Query查询对象
String jpql = "select count(custId) from Customer";
Query query = em.createQuery(jpql);
//ii.对参数赋值
//iii.发送查询,并封装结果
/**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
Object result = query.getSingleResult();
System.out.println(result);
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
/**
* 分页查询
* sql:select * from cst_customer limit 0,2
* jqpl : from Customer
*/
@Test
public void testPaged() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
//i.根据jpql语句创建Query查询对象
String jpql = "from Customer";
Query query = em.createQuery(jpql);
//ii.对参数赋值 -- 分页参数
int page=2;
//起始索引
query.setFirstResult((page-1)*2);
//每页查询的条数
query.setMaxResults(2);
//iii.发送查询,并封装结果
/**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
List list = query.getResultList();
for(Object obj : list) {
System.out.println(obj);
}
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
/**
* 条件查询
* 案例:查询客户名称以‘传智播客’开头的客户
* sql:SELECT * FROM cst_customer WHERE cust_name LIKE ?
* jpql : from Customer where custName like ?
*/
@Test
public void testCondition() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
//i.根据jpql语句创建Query查询对象
String jpql = "from Customer where custName like ? ";
Query query = em.createQuery(jpql);
//ii.对参数赋值 -- 占位符参数
//第一个参数:占位符的索引位置(从1开始),第二个参数:取值
query.setParameter(1,"传智播客%");
//iii.发送查询,并封装结果
/**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
List list = query.getResultList();
for(Object obj : list) {
System.out.println(obj);
}
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
@Test
public void testCondition2() {
//1.获取entityManager对象
EntityManager em = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
//3.查询全部
//i.根据jpql语句创建Query查询对象
String jpql = "from Customer where custName = ? ";
Query query = em.createQuery(jpql);
//ii.对参数赋值 -- 占位符参数
//第一个参数:占位符的索引位置(从1开始),第二个参数:取值
query.setParameter(1,"传智播客1");
//iii.发送查询,并封装结果
/**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
List list = query.getResultList();
for(Object obj : list) {
System.out.println(obj);
}
//4.提交事务
tx.commit();
//5.释放资源
em.close();
}
}