主要目的:
需要做什么?
实现了orm思想的框架:
标准化:
容器级特性的支持:
简单方便:
查询能力:
高级特性
IDENTITY:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long custId;
SEQUENCE :
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")
@SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")
private Long custId;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long custId;
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator="payablemoney_gen")
@TableGenerator(name = "pk_gen",
table="tb_generator",
pkColumnName="gen_name",
valueColumnName="gen_value",
pkColumnValue="PAYABLEMOENY_PK",
allocationSize=1
)
注释:
//@TableGenerator 的定义:
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface TableGenerator {
//表示该表主键生成策略的名称,它被引用在@GeneratedValue 中设置的“generator”值中
String name();
//表示表生成策略所持久化的表名,例如,这里表使用的是数据库中的“tb_generator”。
String table() default "";
//catalog 和 schema 具体指定表所在的目录名或是数据库名
String catalog() default "";
String schema() default "";
//属性的值表示在持久化表中,该主键生成策略所对应键值的名称。例如在“tb_generator”中将
“gen_name”作为主键的键值
String pkColumnName() default "";
//属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加。例如,在
“tb_generator”中将“gen_value”作为主键的值
String valueColumnName() default "";
//属性的值表示在持久化表中,该生成策略所对应的主键。例如在“tb_generator”表中,将“gen_name”
的值为“CUSTOMER_PK”。
String pkColumnValue() default "";
//表示主键初识值,默认为 0。
int initialValue() default 0;
//表示每次主键值增加的大小,例如设置成 1,则表示每次创建新记录后自动加 1,默认为 50。
int allocationSize() default 50;
UniqueConstraint[] uniqueConstraints() default {};
}
//这里应用表 tb_generator,定义为 :
CREATE TABLE tb_generator (
id NUMBER NOT NULL,
gen_name VARCHAR2(255) NOT NULL,
gen_value NUMBER NOT NULL,
PRIMARY KEY(id)
)
1. Persistence 对象主要作用是用于获取 EntityManagerFactory 对象的 。通过调用该类的createEntityManagerFactory 静 态 方 法 , 根 据 配 置 文 件 中 持 久 化 单 元 名 称 创 建EntityManagerFactory。
2. 代码:
//1. 创建 EntitymanagerFactory
@Test
String unitName = "myJpa";
EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);
//创建实体管理类
EntityManager em = factory.createEntityManager();
. 注意:
* 由 于 EntityManagerFactory 是 一 个 线 程 安 全 的 对 象 ( 即 多 个 线 程 访 问 同 一 个EntityManagerFactory 对象不会有线程安全问题),并且 EntityManagerFactory 的创建极其浪费资源,所以在使用 JPA 编程时,我们可以对 EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个 EntityManagerFactory 即可
1. 在 JPA 规范中, EntityManager 是完成持久化操作的核心对象。实体类作为普通 java 对象,只有在调用 EntityManager 将其持久化后才会变成持久化对象。EntityManager 对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过 JPQL 语句查询实体。
2. 我们可以通过调用 EntityManager 的方法完成获取事务,以及持久化数据库的操作
3. 方法说明:
getTransaction : 获取事务对象
persist : 保存操作
merge : 更新操作
remove : 删除操作
find/getReference : 根据 id 查询
1. 在 JPA 规范中, EntityTransaction 是完成事务操作的核心对象,对于 EntityTransaction在我们的 java 代码中承接的功能比较简单
2. 用法:
begin:开启事务
commit:提交事务
rollback:回滚事务
加载配置文件创建实体管理器工厂
根据实体管理器工厂,创建实体管理器
内部维护了很多内容:
EntityManagerFactory的创建过程比较浪费资源
创建事务对象,开启事务
EntityManager对象:实体类管理器
Transaction: 对象: 事务
增删改查操作
提交事务
释放资源
创建maven工程导入坐标
需要配置jpa的核心配置文件
编写客户的实体类
配置实体类和表,类中属性和表中字段的映射关系
保存客户到数据库中
完成基本CRUD案例
查询全部
分页查询
统计查询
条件查询
排序
由于 JPA 是 sun 公司制定的 API 规范,所以我们不需要导入额外的 JPA 相关的 jar 包,只需要导入 JPA 的提供商的 jar 包。我们选择 Hibernate 作为 JPA 的提供商,所以需要导入 Hibernate的相关 jar 包
下载网址:
http://sourceforge.net/projects/hibernate/files/hibernate-orm/5.0.7.Final/
页面显示如下图:
<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>
/*创建客户表*/
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;
public class Customer implements Serializable {
private Long custId;
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
private String custAddress;
private String custPhone;
get方法和set方法...
toString方法...
}
/**
* * 所有的注解都是使用 JPA 的规范提供的注解,
* * 所以在导入注解包的时候,一定要导入 javax.persistence 下的
*/
@Entity //声明实体类
@Table(name="cst_customer") //建立实体类和表的映射关系
public class Customer {
@Id//声明当前私有属性为主键
@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;
getset和toString方法省略...
}
@Entity
作用:指定当前类是实体类。
@Table
作用:指定实体类和表之间的对应关系。
属性:
name:指定数据库表的名称
@Id
作用:指定当前字段是主键。
@GeneratedValue
作用:指定主键的生成方式。。
属性:
strategy :指定主键生成策略。
@Column
作用:指定实体类属性和数据库表之间的对应关系
属性:
name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的 DDL
secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性
定义该列所在从表的名字搭建开发环境[重点]
<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="myJpa" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProviderprovider>
<properties>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost:3306/ssh" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="111111" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
properties>
persistence-unit>
persistence>
问题:
代码:
package cn.itcast.util;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* JpaUtils
* hasee
* 2018/12/16
* 16:02
*
* @Version 1.0
**/
/*
* jpa工具类
*
* 解决实体管理器工厂的浪费资源和耗时问题
* 通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象
* 1. 第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用方法创建一个EntityManager对象
* 2. 第二次方法getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象
*
*
* */
public class JpaUtils {
private static EntityManagerFactory factory=null;
//1. 加载配置文件,创建entityManagerFactory
static {
factory=Persistence.createEntityManagerFactory("myJpa");
}
/*
* 获取EntityManager对象
* */
public static EntityManager getEntityManager(){
return factory.createEntityManager();
}
}
package cn.itcast.test;
import cn.itcast.domin.Customer;
import cn.itcast.util.JpaUtils;
import org.junit.Test;
import javax.persistence.*;
/**
* JpaTest
* hasee
* 2018/12/16
* 15:01
*
* @Version 1.0
**/
public class JpaTest {
/*
*
* 测试jpa的保存
* 案例:保存一个客户到数据库中;
* Jpa的操作步骤
* 1. 加载配置文件创建工厂(实体管理类工厂)对象
* 2. 通过实体管理类工厂获取实体管理器
* 3. 获取事务对象,开启事务
* 4. 完成增删改查操作
* 5. 提交事务(回滚事务)
* 6. 释放资源
* */
@Test
public void testSave(){
//1. 加载配置文件创建工厂(实体管理器工厂)对象
// EntityManagerFactory factory=Persistence.createEntityManagerFactory("myJpa");
// //2. 通过实体管理器工厂获取实体管理器
EntityManager em=JpaUtils.getEntityManager(); //通过工具类创建实体管理器
//3. 获取事务对象,开启事务;
EntityTransaction tx=em.getTransaction(); //获取事务对象
tx.begin(); //开启事务
//4. 完成增删改查操作:保存一个数据到数据库中
//4.1 创建一个实体类
Customer customer=new Customer();
customer.setCustName("暗余");
customer.setAddress("成都");
customer.setCustPhone("15982131554");
customer.setCustLevel("5");
// 4.2 保存操作
em.persist(customer);
//5.提交事务
tx.commit();
//6. 释放资源
em.clear();
//通过工具类创建实体类管理器后,factory不必关闭资源,因为它是一个公共的factory,后面其他线程如果需要使用此factory就可以直接使用了;
// factory.close();
}
//根据id查询客户
/*
* 使用id查询客户
* 使用find方法查询:
* 1. 查询的对象就是当前客户对象本身
* 2. 在调用find方法的时候,就会发送sql语句查询数据库
* 特点:
* 立即加载
* 1. 它是在调用find方法本身,而且是在调用find方法的时候就已经完成查询
* 2. 使用它会浪费内存效率,所以我们一般使用getReference方法进行查询;
* */
@Test
public void testFind(){
//1.通过工具类获取EntityManager
EntityManager entityManager=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=entityManager.getTransaction();
transaction.begin();
//3. 增删改查
/*
* find: 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值 (l是必须要带上的,否则会报错)
*
* */
Customer customer=entityManager.find(Customer.class,1l);
System.out.println(customer);
//4. 提交事务
transaction.commit();
//5. 释放资源
entityManager.close();
}
/*
* 根据id查询用户
* getReference方法
* 1. 获取的对象是一个动态代理对象
* 2. 调用getReference方法不会立即发送sql语句查询数据库
* * 当调用查询结果对象的时候,不会发送查询的sql语句,什么时候用,什么时候发送sql语句查询数据库
* 查询的特点:
* 延迟加载(懒加载)
* 1. 什么时候用,什么时候才会加载
* 2. 得到的是一个动态代理对象
* */
@Test
public void testReference(){
//1.通过工具类获取EntityManager
EntityManager entityManager=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=entityManager.getTransaction();
transaction.begin();
//3. 增删改查
/*
* find: 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值 (l是必须要带上的,否则会报错)
*
* */
Customer customer=entityManager.getReference(Customer.class,1l);
System.out.println(customer);
//4. 提交事务
transaction.commit();
//5. 释放资源
entityManager.close();
}
/*
* 删除
* */
@Test
public void testRemove(){
//1.通过工具类获取EntityManager
EntityManager entityManager=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=entityManager.getTransaction();
transaction.begin();
//3. 增删改查-- 删除客户
//3.1 根据客户id查询用户
Customer customer=entityManager.find(Customer.class, 1l);
//3.2 根据客户查询得到的对象删除用户
entityManager.remove(customer);
//4. 提交事务
transaction.commit();
//5. 释放资源
entityManager.close();
}
/*
*
* 更新
* merge(Object)
* */
@Test
public void testUpdate(){
//1.通过工具类获取EntityManager
EntityManager entityManager=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=entityManager.getTransaction();
transaction.begin();
//3. 增删改查-- 更新操作
//i 查询客户
Customer customer=entityManager.getReference(Customer.class, 2l);
customer.setCustName("暗余大神");
//ii 更新客户
entityManager.merge(customer);
//4. 提交事务
transaction.commit();
//5. 释放资源
entityManager.close();
}
}
package cn.itcast.test;
import cn.itcast.util.JpaUtils;
import org.junit.Test;
import org.omg.IOP.ENCODING_CDR_ENCAPS;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import java.util.List;
/**
* JpqlTest
* hasee
* 2018/12/16
* 20:05
*
* @Version 1.0
**/
/*
* 测试jpql查询
* 1. 创建query查询对象
* 2. 对参数进行赋值
* 3. 查询,并得到返回结果
*
* */
public class JpqlTest {
/*
*
* 查询全部:
* jpql:from cn.itcast.domain.Customer
* sql: SELECT * FROM cst_customer
* */
@Test
public void testFindAll(){
//1. 获取entityManager对象
EntityManager em=JpaUtils.getEntityManager();
//2.1获取事务
EntityTransaction tx=em.getTransaction();
//2.2开启事务
tx.begin();
//3. 查询全部
// 全限定名方式:String jpq1="from cn.itcast.domin.Customer";
//支持简写
String jpq1="from Customer";
//4. 创建Query查询对象,query对象才是执行jpql的对象;
Query query=em.createQuery(jpq1);
//5. 发送查询并封装结果集
List list=query.getResultList();
for (Object obj : list) {
System.out.println(obj);
}
//6. 提交事务
tx.commit();
//7.释放资源
em.close();
}
/*
* 倒序DESC
*
* 倒序查询
* sql:SELECT * FROM cst_customer ORDER BY cust_id DESC
* jpql: from Customer order by custId
*
* */
@Test
public void testOrders(){
//1. 获取entityManager对象
EntityManager em=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=em.getTransaction();
transaction.begin();
//3. 查询事务
String jpq1="from Customer order by custId";
Query query=em.createQuery(jpq1); //创建Query查询对象,query对象才是执行jpq1的对象
// 发送查询,并封装结果集
List list=query.getResultList();
for (Object obj : list) {
System.out.println(obj);
}
//4. 提交事务
transaction.commit();
//5. 释放资源
em.close();
}
/*
* 统计Count
*
* 使用jpql查询,统计客户的总数
* sql: SELECT COUNT(cust_id) FROM cst_customer
* jpql: select count(sustId) from Customer
*
* */
@Test
public void testCount(){
//1. 获取entityManager对象
EntityManager em=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=em.getTransaction();
transaction.begin();
//3. 查询
//3.1 根据jpql语句创建Query查询对象
String jpql="select count(custId) from Customer";
Query query=em.createQuery(jpql);
//3.2对参数赋值
//3.3 发送查询并封装结果
/*
* getResultList:直接将查询结果封装为list集合
* getSingleResult: 得到唯一的结果集
*
* */
Object result=query.getSingleResult();
System.out.println(result);
//4. 提交事务
transaction.commit();
//5. 释放资源
em.close();
}
/*
* 分页查询Limit
*
* sql: select * from cst_customer limit 0,2
* jqpl: from Customer
*
*
*
* */
@Test
public void testPaged(){
//1. 获取entityManager 对象
EntityManager em=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=em.getTransaction();
transaction.begin();
//3. 查询
//3.1 根据jpql语句查询创建Query查询对象
String jpql="from Customer";
Query query=em.createQuery(jpql);
//3.2 对参数赋值 -- 分页参数
//起始索引
query.setFirstResult(0);
//每页查询的条数
query.setMaxResults(2);
//3.3 发送查询,获取结果
List list=query.getResultList();
for (Object obj : list) {
System.out.println(obj);
}
//4. 提交事务
transaction.commit();
//5. 关闭资源
em.close();
}
/*
*
* 条件查询
* 案例:查询客户名称以:“暗”开头的用户
* sql:select * from cst_customer where cust_name LIKE ?
* jpql: form Customer where custName like ?
*
* */
@Test
public void testCondition(){
//1. 获取entityManager 对象
EntityManager entityManager=JpaUtils.getEntityManager();
//2. 开启事务
EntityTransaction transaction=entityManager.getTransaction();
transaction.begin();
//3. 查询
//3.1 根据jpql语句创建Query查询对象
String jpql="from Customer where custName like ? ";
Query query=entityManager.createQuery(jpql);
//3.2 对参数赋值
query.setParameter(1,"%暗%");
/*
* getResultList: 直接将查询结果封装为list集合
* getSingleResult: 得到唯一的结果集
*
* */
List list=query.getResultList();
for (Object obj : list) {
System.out.println(obj);
}
// 4. 提交事务
transaction.commit();
//5. 关闭资源
entityManager.close();
}
}