提到JPA、我们先说一说ORM思想
ORM:Object-Relational Mapping表示对象关系映射。我们在使用面向对象语言时候,通过ORM建立实体类与数据库表之间的关系,就可把对象映射到关系型数据库中,到达操作实体就可以操作数据的目的。
向我们学习的Mybatis就是常见的ORM框架的实现,还有我们要学习的JPA、Hibernate框架都是ORM思想的实现
引入:
关于以前的JDBC操作,我们知道
- 需要书写SQL语句
- 加载驱动、建立连接、创建处理对象、占位符号进行赋值、执行语句、使用结果集进行接收和数据
什么是JPA:Java Persistence API就是java持久化API的缩写,是一套规范,是由抽象类和接口构成的;
类似我们的JDBC规范,向外暴露接口,不同的厂商去做不同的实现。
下面说下Hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将实体类与数据库表建立映射关系,是一个全自动的ORM框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以任意的使用对象编程思维来操纵数据库。
我们要学的JPA本质上就是ORM规范,而不是ORM框架,JPA并未提供ORM的实现,只是制定了一些规范。
JPA和Hibernate的关系:
大概实现一个JPA的代码:
建立一个maven工程,导入hibernate对JPA支持依赖和和数据库依赖
既然是建立实体类和数据库表的联系,
数据库建表
/*创建客户表*/
CREATE TABLE tbl_stu (
stu_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '编号(主键)',
stu_name varchar(32) NOT NULL COMMENT '姓名',
stu_sex char(1) DEFAULT NULL COMMENT '性别',
stu_address varchar(128) DEFAULT NULL COMMENT '联系地址',
stu_phone varchar(64) DEFAULT NULL COMMENT '联系电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
实体类
@Entity
@Tble(name="tbl_stu")
public class student implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="stu_id")
private Long stuId;
@Column(name="stu_name")
private String stuName;
@Column(name="stu_sex")
private String stuSex;
@Column(name="stu_address")
private String stuAddress;
@Column(name="stu_phone")
private String stuPhone;
getter、setter、toString方法....
}
使用的注解配置:
-
@Entity:声明此类是一个实体类
-
@Table(name=“对应的数据库表名”):建立实体类和数据库的连接
-
@Id:对于实体所对应的数据库的主键
-
@GeneratedValue(xxx):配置主键ID的生成策略
-
strategy=GenerationType.IDENTITY:自增策略,要求是需要底层数据库需要提供自增功能,比如mysql
-
strategy=GenerationType.SEQUENCE:序列,要求是需要底层数据库需要提供序列功能,比如Oracle
-
strategy=GenerationType.TABLE:自增,这是JPA给提供的机制,维护一张表的形式棒id进行赋值
-
strategy=GenerationType.AUTO:由程序自动选择生成策略
-
-
@Column:对应数据库字段和实体属性
-
name:指定列名称
-
unique:是否唯一,默认false
-
nullable:是否可以为空。默认true
-
inserttable:是否可以插入
-
updatetable:是否可以更新
-
然后就是配置JPA的核心配置文件persistence.xml文件 ,放置在resource下的MATE-INFO文件夹下面,
引入xml2.0的配置
有一个persistence-unite持久化单元的标签
标签里
JPA的实现方式 persistenceprovider
数据库的配置 javax.persistence.jdbc.user
实现方的配置 showsql 和是否创建表
<?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="自定义名称" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>
持久化单元中配置jpa的实现方式,和实现方hibernate的配置信息
<!--jpa的实现方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--可选配置:配置jpa实现方的配置信息-->
<properties>
<!-- 数据库信息
以前:driver
现在:javax.persistence.jdbc.driver
-->
<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:///jpa"/>
<!--配置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>
有了核心配置和实体对象,接下来就操作一把
//1.首先获取核心配置文件 得到一个实体管理器工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("自定义的Jpa名称");
//2.使用工厂构建实体管理器对象
EntityManager manager = factory.createEntityManager();
//3.根据管理器对象获取事务对象,开启事务
EntityTranscation tx = manager.gettransaction();
tx.begin();
//4.进行操作 提交事务
manager.merge();//更新
manager.remove();//删除
manager.find();//查找 立即查找
manager.getReference();//懒加载
manager.persist();//保存
tx.commit();
//5.释放资源
manager.close();
factory.close();
Persistence对象:此对象的主要功能是用来获取EntityMangerFactory对象的,根据持久化单元的名称进行获取
EntityMangerFactory对象:此接口主要是用来创建EntityManger对象;此对象是一个线程安全的对象,并且创建对象是一个浪费资源的操作,所以在JPA编程的过程只需要存在一个EntityManagerFactory对象即可。
EntityManger对象:是用于主要操作的对象,调用内部实现好的方法
主要方法:
getTransaction : 获取事务对象
persist : 保存操作
merge : 更新操作
remove : 删除操作
find/getReference : 根据id查询
find方法和getReference方法,这两个方法的参数和调用方式都相同;find方法是立即加载,就是在调用的时候直接执行查询语句;gerReference方法是延迟加载或懒加载,在调用的时候不会直接执行查询语句,而是在使用到查询对象的时候才会执行查询语句。
- find方法:
- 查询的时候就是当前对象本身
- 在调用find方法的时候就会直接执行sql语句
- getReference方法:
- 查询到的是一个代理对象,而不是对象本身
- 不会直接执行sql,是什么时间使用什么时间执行sql
CRUD操作
find方法 会根据id查询 立即加载
getReference方法 会根据id查询 懒加载
remove方法 删除 先根据id查询 在删除 sql还是根据id进行删除
merge修改,先进行查询 在进行修改
presist方法 保存
了解了JPA的基本执行流程,来再看一下JPA还支持一种查询语句叫JPQL(Java Persistence Query Language)java持久化查询语句。
JPQL是一种可以移植的查询语言,是一种面向对象的查询语言,其写法与sql语法类似,并且完全面向对象,书写通过类名和属性访问,而不是表名和表的属性;
例:
//sql:SELECT * FROM Student ORDER BY stu_id DESC stu_id是数据库字段
//jpql:from Student order by StuId desc StuId是对象的属性
操作步骤:
//1.首先获取核心配置文件 得到一个实体管理器工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("自定义的Jpa名称");
//2.使用工厂构建实体管理器对象
EntityManager manager = factory.createEntityManager();
//3.根据管理器对象获取事务对象,开启事务
EntityTranscation tx = manager.gettransaction();
tx.begin();
//查询全部
String jpql = "from Student "; //JPQL语句
Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象
//4.进行操作 提交事务
query.getResultList();
tx.commit();
//5.释放资源
manager.close();
factory.close();
当然不仅仅只有这些方法,还有类似sql的分页,条件,排序查询等操作
分页查询:
条件查询:
jpql:from Student where stuName like ?
排序查询:
jpql:from Student order by stuAge desc