JPA规范的理解与应用

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()  

原理

  1. 通过JdkDynamicAopProxy的invoke方法创建了一个动态代理对象
  2. SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD
  3. 通过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")  //对方实体类中的属性名称

猜你喜欢

转载自blog.csdn.net/mrhs_dhls/article/details/107684726
今日推荐