平时使用的持久化框架就是jpa,年前就看了一部分,对用法和原理有了一点点的理解,对做项目真的还是挺有帮助的,这里有介绍了我看过大部分的jpa的用法。好久都没有更博客了,快放假的时候就开始放纵自己了,没有看点东西,也没有锻炼,外加新年一共胖了五斤,最近有时间在的锻炼减肥,自从15年瘦下来之后,16年17年我的体重几乎没有什么改进,而且每次跑步的公里数也就5km左右,太惯着自己,最近开始10km、15km了,当然常规还是10km,不能不进步呀。

  • ORM
  • jpa基本介绍
  • jpa的功能
    • (1)JPA的CRUD操作
    • (2)通过jpql语句进行查询
    • (3)动词findBy查询
    • (4)动态分页查询
    • (5)原生查询
    • (5)一对一、多对多查询
ORM

熟悉框架之前必须要知道ORM是什么,因为jpa就是一个ORM框架。
- (1)定义:ORM英文全写Object relational mapping,也就是英文的表面意思对象关系映射,关系型数据库和对象之间的一一映射,如果有个用户表user【id、userName、pwd】、如果建立对象之间的一一映射,那么我们也需要建相应的类User.class,User类的属性和数据库要一一对应,User类存在的属性,必须要在数据库表内找到相对应的属性相对应,但是数据库表中存在的属性,在类中不一定要存在,如果不对该字段进行任何的操作,可以在类中不定义对应的属性。
- (2)优势:程序中做的大部分的工作就是对输入数据做一些业务逻辑操作,目的是完成对数据的CRUD操作,最终持久化操。对数据库模型(ORM对象)的操作归根结底也就是对数据库的操作,先对ORM对象进行业务逻辑操作,然后持久化,最终完成对数据的操作。

jpa基本介绍
  • (1)与hibernate的关系:jpa是标准,实际上,jpa只是定义了接口,实现都是hibernate在做。
  • (2)jpa存在的目的:让spring实现持久化操作,spring本来对第三方框架的整合上的特别的好。
  • (3)提供的功能:一般的框架都有一个对象操作DB(数据库),hibernate的session、mybatis的sqlSession,jpa的entityManager。这几个框架我都用过,仅仅一点点,也可以说说不会,当初hibernate我用的时候配置还是比较繁琐的,但是我的印象中它好像不用写sql语句。mybatis,有一个和数据相对应的mapper.xml文件,和数据库一一对应,可以写sql语句,mapper中写的sql可以进行各种if判断的,感觉也很强大的。一般的ORM框架只能提供CRUD操作,但是jpa可以提供逻辑处理的。刚看这里的时候我还不太理解这个地方是什么意思,提议的去查了一下业务逻辑的定义。对于不同的功能有这不同的实现,不同的实现,实现这些功能的核心代码就叫做业务逻辑,如果我们的功能是实现求两个数的和,那么我们程序中的代码实现也就是业务逻辑处理。
  • (4)dao:data access object数据库访问对象,跟respository是一样的。
jpa的功能
  • (1)前言:
    1)具体实现功能包括几种:直接实现JpaRepository的接口,可以通过jpa提供的方法对数据库进行操作,jap自定义接口中的@Query自定义jpql语句查询、findBy动词自定义查询语句、动态分页查询、原生sql查询。

    2)在我定义的TeacherRepository接口中,实现了接口JpaSpecificationExecutor和
    JpaRepository。JpaRepository定义了一组标准的接口,CrudRepository继承了Repository接口,定义了一组CRUD的操作方法,也就是说只要我们的类实现JpaRepository接口就行了对模型对象进行CRUD操作。JpaSpecificationExecutor接口提供了一组基于标准JPA Criteria查询相关的方法,也就是分页动态查询相关的操作。
    3)在使用jpa的时候真的”针对接口编程“了,除了定义方法外没有做任何的实现,有的时候甚至在xxxRespository类中没有定义任何的方法,那就说明jpa提供的方法足以满足程序功能的需求了,正常接口应该需要实现类的呀,如果定义了实现类实现了
    JpaSpecificationExecutor和JpaRepository接口,那么实现类中会有几十个实现方法,实现几十个方法还怎么玩。其实jpa给我们提供的具体的实现方法不需要我们做其他的操作。
public class SimpleJpaRepository<T, ID extends Serializable>
implements JpaRepository<T, ID>,JpaSpecificationExecutor<T>

当然也可以定义实现类的,但是只需要放在 xxxRespository一个文件下即可,我写的中impl形式的类都用来写自定义的sql,下面有介绍。jpa给我们提供了SimpleJpaRepository实现类,所以只需要我们定义接口就可以了。

(1)JPA的CRUD操作
     <S extends T> S save(S var1);<S extends T> Iterable<S> save(Iterable<S> var1);T findOne(ID var1);long count();void delete(ID var1);void delete(T var1);void delete(Iterable<? extends T> var1);void deleteAll();
   @Overridepublic UserEntity save(UserEntity user) {logger.info("user:[{}]", JSON.toJSON(user));testRepository.save(user);return user;}

直接通过注入的xxxRespository.save即可保存,如果这个user对象存在会替换DB中的数据。delele时,如果如数要删除实体或者该条数据的唯一标识符即可。

(2)通过jpql语句进行查询
  @Query(value = "from StudentEntity s where s.s_name =?1")StudentEntity queryByName(String name);

在定义的xxxRepository类型直接,定义方法即可,上面接口中定义的方法就是根据学生的姓名查找学生实体。

(3)动词findBy查询
UserEntity findByNameAndPassword(String name,String password);

根据用户和密码查询用户的信息,findBy+各种条件,如果有兴趣了解详细的命名规则参考博客 http://blog.csdn.net/sbin456/article/details/53304148。

(4)动态分页查询
 @Overridepublic List<ScEntity> getScDynamicQuery(int pageSize, int size) {Specification<ScEntity> specification = specificationConfig.where();Sort sort = new Sort(Sort.Direction.ASC, "id");Pageable pageable = new PageRequest(pageSize,size, sort);Page<ScEntity> page = scRepository.findAll(specification,pageable);List<ScEntity> list = page.getContent();if(list.size()>0){for(ScEntity entity : list){System.out.println(entity.getId());}}return page.getContent();}
//where条件代码 定义在SpecificationConfig类中public Specification<T> where(){return new Specification() {@Overridepublic Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {/*** 1 Root ORM对象和数据表对应,* 2 CriteriaBuilder 相当于SQL的where条件* 3 CriteriaQuery是一个顶层的查询,它包含查询的各个部分select 、from、where、group by、order by*/List<Predicate> predicates = new ArrayList<Predicate>();return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();}};}

1)Specification规范类,也就查询所需要的条件,归根揭底我们提供能的条件,组装了jpa能够识别的sql条件。SpecificationConfig类是一个泛型类,编译时决定Specification的类型,这样做的好处是,需要类似Specification条件的类可以进行复用。上面代码返回的Specification类型就是ScEntity的。
2)scRepository.findAll(specification,pageable)中的findAll就是JpaSpecificationExecutor接口中提供的方法,Pageable类是分页类,它提供了查询第几页,以那个属性如何排序展示结果。findAll方法的参数中Specification类型是动态变化的,也就是根据Specification的类型的变化,findAll展现出不同类型的结果,它其实是一个策略模式,我的理解策略模式跟多态性有相近的意思,运行时动态的根据对象的类型展现不同的结果。
3)下面说说这个Specification类:

public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

在我的SpecificationConfig类型,并没有实现Specification这个接口,但是我需要组装查询条件,需要返回一个Specification类型的类,接口不能初始化,所以在这里通过匿名内部类来实现这个接口。
定义查询条件:这个条件是我编的,相当于
where uuid like %uuid% and accNo =”acctNo“。

 List<Predicate> list  = new ArrayList<>();String uuid = "";list.add(cb.like(root.<String>get("uuid"), "%"+ uuid +"%" ));String acctNo= "";ist.add(cb.equal(root.get("acctNo"), acctNo));return query.where(list.toArray(new Predicate[list.size()])).getRestriction();

Root类相当于ORM对应的模型类,root是从模型中获取模型属性值的。
CriteriaBuilder:创建查询条件的。
Query:相当于一个顶层查询类,在这类相当于构建where条件的。

(5)原生查询

如果涉及到的字段比较多,而且是一些报表统计类的查询表的话,通过无论通过jpa动态查询还是通过其他的查询可能都是比较繁琐的,jpa也是支持原生sql查询的,下面提供两种查询方式,但是getResultList()返回结果有三种形式:

  public List<ScEntity> findBySId(Long sId){String sql = "select * from sc where s_id = '" + sId + "'";Query query = entityManager.createNativeQuery(sql);List<ScEntity> list = query.getResultList();//List listMap = query.getResultList();String sqlStr = "select s from ScEntity s where s.s_id = '" + sId + "'";query = entityManager.createQuery(sqlStr) ;List<ScEntity> listStr = query.getResultList();return list;}

1)createNativeQuery:参数sql 是根据数据表的名字而构造的查询sql语句。
2)createQuery:参数是以对象模型而构造的查询语句。
3) 看我注释掉的那句话,如果你是做用户报表类的查询的话,查询结果不可能是一个表内的,如果是一个表内的话你可能也只是想查询出几个属性值,那么我们的list返回结果就不是个实体类型的,而需要我们去解析,其实返回的是一个键值对,下面展示一下我做过的报表查询类的代码与解析。

Query query = entityManager.createNativeQuery(columsSql);
query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List list = query.getResultList();
//解析Map<String,String> map = new HashMap<>();if(list.size() > 0){for(Object o :list){Map<String,String> temp =(HashMap)o;for (Map.Entry entry : temp.entrySet()){if(entry.getValue() == null){map.put(entry.getKey().toString(),BigDecimal.ZERO.toString());}else{map.put(entry.getKey().toString(),entry.getValue().toString());}}}}

所有的查询结果都在这个map中展示。

(5)一对一、多对多查询

关联查询分为两种:一种是在动态分页中构建的,另一个是在模型对象中构建的。
1)动态分页中构建的查询关系我没有用过,所以我就不介绍了,在我参考的博客里面有。
2)另一个是在对象模型中构建的对象之间的关系,这个我随便介绍一个吧,在这之前简单的介绍一下什么是一对多,多对一,多对多,一对一的关系。一对一:一夫一妻。一对多:古代的皇帝和妃子。多对一:多个妃子都应一个皇帝。多对多:不光皇帝有多个妃子呀,王爷也有呀,两个以上的一对多关系就是多对多的关系。

 /*** 学生跟成绩是一对多的关系,一个学生有多门成绩*/@OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)@JoinColumn(name="s_id", referencedColumnName="s_id",insertable = false, updatable = false)private List<ScEntity> scEntities;/*** 一个学生对应多个老师*/@OneToMany(cascade = CascadeType.REMOVE,fetch = FetchType.LAZY)@JoinColumn(name="s_id", referencedColumnName="s_id",insertable = false, updatable = false)private List<TeacherEntity> thEntity;

通过OneToMany注解标注模型对象之间的关系,通过JoinColumn来指出对象之间通过什么关联,顺便说一下级联:级联就是相关联DB之间的同事操作,CascadeType.REMOVE只的是,如果删除当前的实体,那么跟这个实体相关的数据也会被删除,CascadeType还有很多的操作,可以自己搜一下。fetch指的是关联类的加载方式,如果在一个模型中只有一个关联关系,那么它是懒加载还是立即加载都可以,但是如果存在多个关联关系,例如上面代码中,EAGER加载机制只能立即加载一个类到内存中,其他的类均为LAZY类型的加载方式。否则会报错。

未完待续!

参考博客:http://blog.csdn.net/u010098331/article/details/51700777
https://www.cnblogs.com/dreamroute/p/5173896.html
https://www.cnblogs.com/nicuty/p/6265303.html

spring jpa的基本操作和理解相关推荐

  1. Spring JPA数据+Hibernate+ MySQL + Maven

    在Spring MVC的帮助下开发Web应用程序意味着要创建几个逻辑架构层. 层之一是DAO(存储库)层. 它负责与数据库进行通信. 如果您至少开发了DAO层一次,则应该知道它涉及许多样板代码. Sp ...

  2. spring.jpa配置_使用JPA和Spring 3.1进行事务配置

    spring.jpa配置 1.概述 本教程将讨论配置Spring Transactions ,使用@Transactional批注和常见陷阱的正确方法 . 有关核心持久性配置的更深入讨论,请查看Spr ...

  3. Spring JPA数据+休眠+ MySQL + Maven

    在Spring MVC的帮助下开发Web应用程序意味着要创建几个逻辑架构层. 层之一是DAO(存储库)层. 它负责与数据库进行通信. 如果您至少开发了DAO层一次,则应该知道它涉及许多样板代码. Sp ...

  4. 使用Spring JPA中Page、Pageable接口和Sort类完成分页排序

    显示时,有三个参数,前两个必填,第几页,一页多少个size,第三个参数默认可以不填. 但是发现这个方法已经过时了,通过查看它的源码发现,新方法为静态方法PageRequest of(page,size ...

  5. 最近在研究Spring Data JPA,大家都来说说感受~~ - Spring,JPA - Java - ITeye论坛

    最近在研究Spring Data JPA,大家都来说说感受~~ - Spring,JPA - Java - ITeye论坛 最近在研究Spring Data JPA,大家都来说说感受~~ - Spri ...

  6. Spring JPA 开启原生sql打印

    2019独角兽企业重金招聘Python工程师标准>>> 原生spring项目,使用配置文件(非Spring boot项目) <!-- 配置EntityManagerFactor ...

  7. Spring松耦合的个人理解和代码实例

    Spring松耦合的个人理解和代码实例 理解Spring的松耦合概念,那么我们先来看看一个不使用Sring的实例代码 先看一下整个测试项目案例的结构 正常方式 创建一个接口,这个接口指定车辆的行驶速度 ...

  8. Spring JPA使用CriteriaBuilder动态构造查询

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/mzdljgz/p/11495723 ...

  9. spring 扫描所有_从Spring的几个阶段理解其工作过程

    首发于博客园,https://www.cnblogs.com/ibigboy/p/11150237.html Spring框架非常强大,想要彻底弄懂Spring是非常困难的. 为了便于初学者了解Spr ...

最新文章

  1. 社群分享:涨粉的35个玩法和技巧
  2. Spring事务专题(三)事务的基本概念,Mysql事务处理原理
  3. AFAB 科目要求一个成本会计分配
  4. 同步/异步与阻塞/非阻塞的区别
  5. python输入三个商品_用python3采集shopify站点商品
  6. 求1到N的全排列 (转载)
  7. 2021年中国船舶甲板市场趋势报告、技术动态创新及2027年市场预测
  8. android screencap 源码,android后台截屏实现(3)--编译screencap
  9. SpringSecurity认证基本原理与认证2种方式
  10. 如何把PPT连背景一起复制?
  11. 女人是这样哄的,学以致用
  12. C语言入门 九九乘法表
  13. Hadoop第四天--shell编程
  14. Kvm*虚机中创建虚机
  15. html自动执行bat,bat脚本启动程序 怎么命令bat打开某个文件
  16. 数据库系统概论——关系代数详解
  17. Javascript特效:九宫格布局
  18. java学生成绩管理_java开发的简易学生成绩管理系统
  19. 1124: 两个有序数组合并
  20. 微信公众上传图文素材,报错45166

热门文章

  1. Django之爱鲜蜂项目开发 day01 (二)
  2. 【酷热高温教你给显卡降降温】
  3. 各种常用电子元器件符号
  4. 自然语言理解的概念与发展历史
  5. 微信小程序开发【前端+后端(Java)】附完整源码,拿来接私活简直不要太香
  6. 一个诡异的问题的解决20211008
  7. NVMe1.4b—Sanitize命令
  8. 中望cad2017专业版|中望cad2017sp专业版下载
  9. python屏幕取词getword_GetWord Demo(屏幕取词软件) V5.0.1 官方版
  10. python小程序设计每天定时微信发消息_定时发送微信小程序订阅消息