Em的find方法会使用缓存
em.getReference 使用延迟加载策略 返回的是代理对象;
先查再set就能改了,事务提交会自动更新.提交时会比较对象与表数据,不同就更新
Mysql用limit oracle用rownum
Jpa基于框架进行开发,可以随意切换数据库,跨数据库开发
需求
保存一个客户到客户表
步骤
1.建表
2.创建工程
3.引入依赖
4.建立实体类
建立类和表的对应关系(加注解)
@Entity 表示这个类是JPA的一个类,默认表明和类名对应
@Table(name="cst_customer") //如果表明和类名一致,可以省略
建立属性与列的对应关系
1.主键属性上的注解
@Id //主键属性
@Column(name="cust_id") //如果列名和属性名一致,可以省略
@GeneratedValue(strategy=GenerationType.IDENTITY) //指定主键生成策略
2.非主键属性上的注解
默认情况下不用加注解(要求列名和属性名一样)
@Column(name="cust_name") //不一样就要写出来
5.编写jpa的核心配置文件 persistence.xml
在src下创建一个META-INF文件夹(固定写法)
引入约束
file-new-edit file template-jpa-deployment-persistence_2_0.xml拿过来即可
persistence-unit//持久化单元 transaction-type//指定事务类型
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--指定JPA规范的提供商-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/springdatajpa"/> name 固定写法
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
<property name="hibernate.show_sql" value="true"/> 是否展示sql语句 value="true"展示
<property name="hibernate.format_sql" value="true"/>
<!--
create:每次加载hibernate框架,如果有表,先删除表,再创建表
create-drop:每次加载hibernate框架,如果有表,先删除表,再创建表,当程序结束时,再删除表
update:如果没有表,会创建表,不会打印建表语句;如果有表,会比较实体类和表结构是否一致,如果不一致,就更新表结构
validate:如果没有表,会报错;如果有表,会比较实体类和表结构是否一致,如果不一致,就报错
-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
RESOURCE_LOCAL:本地事务
一个项目只有一个数据库
JTA:分布式事务
业务中有好多操作,跨数据库存在的,要保证操作在同一个事务中
要结合第三方技术(如容器)才能使用
6.代码测试
@Test
public void test1() {
Customer customer = new Customer();
customer.setCustName("九阳");
//创建实体管理器工厂EntityManagerFactory=======SqlSessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//获取实体管理器EntityManager======SqlSession
EntityManager em = factory.createEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
//保存
em.persist(customer);
//提交事务
tx.commit();
//释放资源
em.close();
factory.close();
}
//jpa所有操作包括查询都要放到事务里面去 ★★★
7.hbm2ddl.auto取值的说明
ddl:SQL语句的一种data define language,数据定义语言create drop alter
dml:数据的操纵语言,insert update delete
dql:数据查询语言,select
tcl:事务控制语言 commit rollback
dcl:数据控制语言 grant revoke
hibernate.hbm2ddl.auto
create:每次加载hibernate时,如果有表,先删除表,再建表
好处:不用手动建表
create-drop:每次加载hibernate框架,如果有表,先删表再建表,程序结束时,再删除表
作用:用于做测试,测试数据不保存
update:如果没有表,会创建表但是不会打印建表语句,如果有表,会比较实体类和表结构是否一致,一致啥也不干。如果不一致,更新表结构
validate:如果没有表,会报错;如果有表,会比较类和表结构是否一致,如果不一致,就报错(持久化异常)
生产环境中用update ★★★
8.主键生成策略 @GeneratedValue(strategy=GenerationType.IDENTITY)
IDENTITY
自增,mysql和sql server能自增,oracle不能自增
SEQUENCE
序列,oracle中的一个对象,通过序列模拟一个自增的效果
TABLE
通过表来实现自增的效果,通过表来维护主键,一个通用的
AUTO
自适应,根据底层数据库的不同选择一种策略
mysql 选表策略(hibernate4,5,用table 3是选的identity)
oracle 选序列
生产环境中,底层是mysql用IDENTITY,底层是oracle用SEQUENCE ★★★
9.JPAUtils类
由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory 即可 。
public class JPAUtils {
private static final EntityManagerFactory factory;
//创建EntityManagerFactory
static {
factory = Persistence.createEntityManagerFactory("myJpa");
}
public static EntityManager getEntityManager(){
return factory.createEntityManager();
}
}
测试工具类
@Test
public void test2() {
Customer customer = new Customer();
customer.setCustName("美的");
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(customer);
tx.commit();
em.close();
}
10.查询
/**
* 根据id查询对象
* 立即加载
*/
@Test
public void test1() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Customer customer = em.find(Customer.class, 1L);
System.out.println(customer);
tx.commit();
em.close();
}
@Test
public void test2() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//先检测缓存里是否有id为1的客户对象,没有,就发送sql语句查询数据库得到一个对象,再把该对象存放到缓存里
Customer customer1 = em.find(Customer.class, 1L);
//先检测缓存里是否有id为1的客户对象,有,就直接用缓存的对象,不再发送sql语句
Customer customer2 = em.find(Customer.class, 1L);
System.out.println(customer1 == customer2);
tx.commit();
em.close();
}
友情提示:这个缓存比mybatis缓存强,mybatis缓存鸡肋,查一个数据,放缓从,事务没提交,做一些增删改,缓存立马失效
/**
* 延迟加载
* 返回的是代理对象
*/
@Test
public void test3() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Customer customer = em.getReference(Customer.class, 1L);
System.out.println(customer);
tx.commit();
em.close();
}
11.修改
先查询再修改
事务提交会自动更新
过程:先查出来,事务提交的时候,会比较对象数据是否和表的记录一致,如果不一致,就把对象信息更新到表里面去
对象要和em有关系才会自动更新,否则显示调用更新em.merge(""),这个方法容易丢失数据,不推荐使用
/**
* 先查询,再修改
*/
@Test
public void test4() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Customer customer = em.find(Customer.class, 1L);
customer.setCustLevel("普通客户");
tx.commit();//事务提交,会自动更新
em.close();
}
@Test
public void test5() {
Customer customer = new Customer();
customer.setCustId(3L);
customer.setCustName("美的集团");
// customer.setCustIndustry("家电");
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.merge(customer);
tx.commit();
em.close();
}
12.删除
/**
* 先查询,再删除
先查询,再删除
detached:游离态,脱管 不受管理
persistence: 持久态
*/
@Test
public void test6() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Customer customer = em.find(Customer.class, 3L);
em.remove(customer);
tx.commit();//事务提交,会自动更新
em.close();
}
@Test
public void test7() {
Customer customer = new Customer();
customer.setCustId(1L);
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.remove(customer);
tx.commit();
em.close();
}
13.JPQL
java Persistence Query Language
sql:select * from cst_customer
jpql:from Customer 去掉select * ,将表名换成类名,列名换成属性名,查出的一行数据形成一个对象,放到集合中去返回
//查询所有
em.createQuery("from Customer")
分页查询
//设置分页信息 mysql分页用limit,oracle分页用rownum
查count(*)规定写long
@Test
public void test8() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("from Customer");
//执行查询
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();//事务提交,会自动更新
em.close();
}
@Test
public void test9() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("from Customer where custName like ? or custIndustry = ?");
//给占位符设置值
query.setParameter(1, "%马%");
query.setParameter(2, "家电");
//执行查询
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();//事务提交,会自动更新
em.close();
}
@Test
public void test10() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("from Customer");
//设置分页信息
query.setFirstResult(2);
query.setMaxResults(2);
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();//事务提交,会自动更新
em.close();
}
@Test
public void test11() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("from Customer order by custName,custId desc");
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();//事务提交,会自动更新
em.close();
}
/**
* sum avg count max min
*/
@Test
public void test12() {
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("select count(*) from Customer");
// List<Long> list = query.getResultList();
// System.out.println(list.get(0));
Long total= (Long) query.getSingleResult();
System.out.println(total);
tx.commit();//事务提交,会自动更新
em.close();
}