JPA
简介
JPA 是一套规范,内部是有接口和抽象类组成的。Hibernate 是一套成熟的 ORM 框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)
Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。
使用
1.加载配置文件创建工厂(实体管理器工厂)对象
Persistence的静态方法createEntityManagerFactory("myJpa");持久化单元名称
2.通过实体管理器工厂获取实体管理器
EntityManager em = factory.createEntityManager();
内部维护了数据库信息
维护了缓存信息
维护了所有的实体管理器对象
再创建EntityManagerFactory的过程中会根据配置创建数据库表
3.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction();
tx.begin();
4.完成增删改查操作
em.persist()
em.find() 立即加载
em.getRefrence() 延迟加载
em.merge()
em.remove()
5.提交事务(回滚事务)
tx.commit();
6.释放资源(先关闭实体管理器,后关闭实体管理器工厂)
em.close();
factory.close();
JPQL
简介
JPQL 是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL
使用
1.根据jpql语句创建Query查询对象
2.对参数赋值
3.发送查询,并封装结果
@Test
public void test2() {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
EntityManager em = entityManagerFactory.createEntityManager();
//EntityTransaction tx = em.getTransaction();
//tx.begin();//开启事务
String jpql = "from Customer order by custId desc";
Query query = em.createQuery(jpql);
query.setFirstResult(0);//起始页码
query.setMaxResults(3);//每页条数
List resultList = query.getResultList();
for (Object o : resultList) {
System.out.println(o);
}
}
Spring DATA JPA
简介
Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用 Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦
使用
1.创建工程,导入坐标
2.配置spring的配置文件(配置spring Data jpa的整合)
3.编写实体类,使用jpa注解配置映射关系
4.继承两个接口(JpaRepository,JpaSpecificationExecutor)
5.测试环境测试即可
根据id查询
findOne() :立即加载
getOne () : 延迟加载
保存或者更新
save()
根据id删除
delete()
查询全部
findAll()
原理
- 通过JdkDynamicAopProxy的invoke方法创建了一个动态代理对象
- SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD
- 通过hibernate完成数据库操作(封装了jdbc)
注意
1.springDataJpa 中使用jpql完成 更新/删除操作 默认回滚事务
2.更新操作时要加上@Modifing注解
复杂查询
方法
JpaSpecificationExecutor接口的5个方法
T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
使用
模糊查询
@Test
public void test2() {
//匿名内部类
Specification<Customer> specification = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");
Predicate p1 = criteriaBuilder.like(custName.as(String.class), "%马");
return p1;
}
};
Sort sort = new Sort(Sort.Direction.DESC, "custId");
List<Customer> customers = customerDao.findAll(specification,sort);
for (Customer customer : customers) {
System.out.println(customer);
}
}
分页查询
@Test
public void testSpec4() {
Specification<Customer> specification = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");
Predicate p1 = criteriaBuilder.like(custName.as(String.class), "客户名称");
return p1;
}
};
// 第一个参数:当前查询的页数(从0开始)
// 第二个参数:每页查询的数量
//PageRequest对象是Pageable接口的实现类
Pageable pageable=new PageRequest(0,4);
Page<Customer> page = customerDao.findAll(specification, pageable);
System.out.println(page.getTotalElements());//总条数
System.out.println(page.getTotalPages());//总页数
System.out.println(page.getContent());//得到数据集合
}
}
多表操作
一对多
//声明关系,配置一对多
//@OneToMany(targetEntity = LinkMan.class)
//@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")//配置外键
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)//放弃外键维护
//声明关系,配置多对一
@ManyToOne(targetEntity = Customer.class,cascade = CascadeType.ALL)
@JoinColumn(name = "lkm_cust_id", referencedColumnName = "cust_id")
多对多
//用户到角色的多对多关系
@ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
@JoinTable(name = "sys_user_role",
//joinColumns,当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
)
//角色到用户的多对多关系
@ManyToMany(targetEntity = User.class)//对方对象字节码对象
@JoinTable(name = "sys_user_role",//中间表名称
//joinColumns,当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "role_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "user_id")}
)
//一方放弃外键维护
@ManyToMany(mappedBy = "roles") //对方实体类中的属性名称