网站续费话术,上海十大广告公司排名,系网站建设工作总结,网站建设方维Spring Data JPA系列
1、SpringBoot集成JPA及基本使用
2、Spring Data JPA Criteria查询、部分字段查询
3、Spring Data JPA数据批量插入、批量更新真的用对了吗
4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作
5、Spring Data JPA自定… Spring Data JPA系列
1、SpringBoot集成JPA及基本使用
2、Spring Data JPA Criteria查询、部分字段查询
3、Spring Data JPA数据批量插入、批量更新真的用对了吗
4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作
5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用
6、【源码】Spring Data JPA原理解析之Repository的自动注入一
7、【源码】Spring Data JPA原理解析之Repository的自动注入二
8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码
9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理一
10、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理二
11、【源码】Spring Data JPA原理解析之Repository自定义方法添加Query注解的执行原理
12、【源码】SpringBoot事务注册原理
13、【源码】Spring Data JPA原理解析之事务注册原理
14、【源码】Spring Data JPA原理解析之事务执行原理
15、【源码】SpringBoot编程式事务使用及执行原理
16、【源码】Spring事务之传播特性的详解
17、【源码】Spring事务之事务失效及原理
18、【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理
19、【源码】Spring Data JPA原理解析之Auditing执行原理
20、Spring Data JPA使用及实现原理总结
前言
《 Spring Data JPA系列》博文已经写了19篇对于Spring Data JPA还有其他的知识点该系列博文暂时先写这些。该系列从入门到高级、再到源码解读分享了Spring Data JPA在开发中最常用的技术点和实现原理。本篇对《Spring Data JPA系列》做一个总结。
Spring Data JPA简介
Spring Data JPA是Spring提供的一套简化JPA开发的框架按照约定好的方法名命规则写DAO层接口可以在不写接口实现的情况下实现对数据库中Table的操作同时提供了除CRUD操作之外的许多功能如分页、复杂查询等。
Repository接口类型
在JPA中通过自定义Repository接口实现对数据库的操作。Repository接口的接口方法类型为以下三类
1第一类Repository接口为继承JpaRepositoryImplementation接口的接口方法该接口提供并自动实现了对实体类的CRUD等的操作
2通过方法命名规则自定义接口方法无需写SQL或HQL实现数据库表的操作主要针对数据库表的查询、删除操作 方法名称规则 操作关键字 By 属性名称属性名称的首字母大写 查询条件首字母大写 操作关键字包括 find | read | get | query | search | stream | count | exists | delete | remove 查询条件包括 And | Or | Is | Equals | Between | LessThan | Before | LessThanEqual | GreaterThan | After | GreaterThanEqual | IsNull | IsNotNull | NotNull | Like | NotLike | StartingWith | EndingWith | Containing | OrderBy | Not | In | NotIn | True | False | IgnoreCase | OrderBy 3通过Query注解添加SQL或HQL自定义接口方法实现数据库表的操作 在Query注解中支持三类查询语句的书写形式分别如下 a通过Query注解的value属性填写HQL语句 b通过Query注解的value属性填写SQL语句nativeQuery属性设置为true c通过Query注解的name属性填写对应的queryName。其中queryName为在实体类中通过NamedQueries、NamedQuery注解添加的HQL语句 详见SpringBoot集成JPA及基本使用-CSDN博客 EntityManager实现的数据库操作
在JPA中除了通过Repository接口实现对数据库的操作以外还可以通过EntityManager编码实现数据库操作。
Java Persistence APIJPA中的EntityManager是一个接口在JPA规范中EntityManager扮演着执行持久化操作的关键角色。普通Java对象只有被EntityManager持久化之后才能转变为持久化对象保存到数据库中。它不仅可以管理和更新Entity对象还可以基于主键查询Entity对象通过JPQL语句进行Entity查询甚至通过原生SQL语句进行数据库更新及查询操作。
EntityManager提供以下功能 1创建、更新和删除数据EntityManager中的persist()、merge()和remove()方法分别用于插入、更新和删除数据库记录 2查询数据EntityManager的find()和createQuery()方法用于查询数据 3管理实体的生命周期EntityManager的flush()方法用于将持久性上下文同步到基础数据库进行持久化操作 4事务管理EntityManager的getTransaction()方法用于获取当前事务可以对事务进行提交或回滚 5执行原生SQLEntityManager的createNativeQuery()方法用于执行原生SQL。对于原生SQL需要考虑不同数据库的各自实现 6创建CriteriaBuilderEntityManager的getCriteriaBuilder()方法用于获取CriteriaBuilder。通过CriteriaBuilder实现使用Criteria API查询数据 详见Spring Data JPA数据批量插入、批量更新真的用对了吗-CSDN博客 Criteria查询
JPA的Repository接口操作数据库时无法很好的支持动态条件查询Criteria查询可以很好的解决这个问题。
Criteria查询的API主要包括
1CriteriaBuilder用于构造条件查询、复合选择、表达式、谓词和排序
2CriteriaQuery定义了特定于顶级查询的功能包含了查询的各个部分。如select结果集、where条件、group by、order by等。在CriteriaQuery指定返回值结果集
3Root定义Criteria查询的根对象Criteria查询的根定义为实体类型它与SQL查询中的FROM子句类似定义了查询的FROM子句中能够出现的类型。可以有多个查询根对象
4Expression运算表达式。用在查询语句的select、where和having子句中该接口有isNull、isNotNull和in方法。可通过Root.get(“实体类属性”)获得Expression对象
5Predicate过滤条件。通过CriteriaQuery.where()方法将Predicate或Expression实例作为条件应用到Criteria查询中 Predicate实例可以通过CriteriaBuilder的条件方法equal、notEqual、gt、ge、lt、le、between、like等创建 Predicate实例也可以通过Expression实例的isNull、isNotNull和in方法获得 复合的Predicate语句可以使用CriteriaBuilder的and、or、andnot方法构建 详见Spring Data JPA Criteria查询、部分字段查询-CSDN博客 JPA多表关系
在JPA中支持多表关系定义及多表级联操作。
多表关系主要相关注解 OneToOne注解表示一对一关系 OneToMany、ManyToOne注解表示一对多关系 ManyToMany注解表示多对多关系 JoinColumn注解标记实体类与数据库的对应关系以OneToOne、OneToMany、ManyToOne三个注解搭配使用 JoinTable注解多对多通常使用中间表关联通过该注解标记关联表以ManyToMany注解搭配使用。属性name为关联表的名称、joinColumns为关联student表的id、inverseJoinColumns为关联Course表的id 多表级联操作是指当一个实体的状态发生改变时关联的其他实体是否同时发生改变。简单理解cascade用于设置当前实体是否能够操作关联的另一个实体的权限。cascade的取值在CascadeType枚举类中定义。 详见Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 实体类Id生成策略
JPA默认支持四种Id生成策略分别为TABLE使用数据库表格保存主键、SEQUENCE使用底层数据库的序列来生成主键、IDENTITY主键由数据库自动生成、AUTO主键由程序控制。通过GeneratedValue注解中的strategy属性指定对应生成策略。
除了以上四种默认支持的策略以外JPA还支持自定义Id生成策略通过实现org.hibernate.id.IdentifierGenerator接口重写generate()方法在方法中返回Id值。
通过GenericGenerator注解指定自定义Id策略的名称name及对应的策略strategy的类并添加GeneratedValue注解的generator属性为GenericGenerator注解的name属性。
复合主键
在Spring Data JPA的实体类中并不支持简单的直接在多个属性中添加Id注解实现复合主键。而是需要先创建一个复合主键类然后在实体类中使用IdClass注解将主键类附加在类中然后在多个主键属性中添加Id主键。
Auditing审计
JPA通过CreateBy、CreateDate、LastModifiedBy、LastModifiedDate四个注解提供对数据库表中的数据记录自动添加操作人及操作时间的审计功能。
在实际开发中可以定义一个抽象父类专门记录操作人及操作信息。在该父类中添加MappedSuperclass注解。
Auditing使用 1在启动类中添加EnableJpaAuditing注解开启Auditing 2在实体类中添加监听器及操作人、操作时间的注解。或者定义一个抽象父类专门记录操作人及操作信息。并添加EntityListeners注解添加AuditingEntityListener监听器 3自定义AuditorAware重写getCurrentAuditor()返回审计员主键实现数据记录的创建人、操作人的自动填充 详见Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用-CSDN博客 Repository自动注入原理
JPA的Repository注入到Spring IOC容器的对象为代理对象其中target为SimpleJpaRepository对象实现了自定义的Repository接口、Repository接口以及TransactionProxy接口主要添加了QueryExecutorMethodInterceptor、TransactionInterceptor等拦截器。
注入的主要执行流程如下
1在SpringBoot中引入spring-boot-starter-data-jpa依赖时会自动注入JpaRepositoriesAutoConfiguration从而注入JpaRepositoryConfigExtension
2在JpaRepositoryConfigExtension的父类RepositoryConfigurationExtensionSupport的getRepositoryConfigurations()方法中获取所有实现Repository接口的类封装成RepositoryConfiguration
3SpringBoot启动时会执行RepositoryConfigurationDelegate的registerRepositoriesIn()方法在该方法中获取2中所有实现Repository接口的类创建对应的BeanDefinition对象其中beanClass为org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean字符串。并执行registry.registerBeanDefinition(beanName, beanDefinition)将Repository类及对应的beanDefinition添加到Spring IOC容器中
4在Spring启动过程中会执行AbstractBeanFactory.doGetBean()方法先从Repository的BeanDefinition中获取beanClass为JpaRepositoryFactoryBean类名然后创建JpaRepositoryFactoryBean对象。执行afterPropertiesSet()方法完成初始化
5在JpaRepositoryFactoryBean的afterPropertiesSet()初始化方法中会调用RepositoryFactorySupport.getRepository()方法。该方法通过代理的的方式创建一个实现了自定义的Repository接口、Repository以及TransactionProxy接口且代理的target为SimpleJpaRepository对象代理添加了QueryExecutorMethodInterceptor、TransactionInterceptor等拦截器。代理的对象保存在repository属性中
6执行了JpaRepositoryFactoryBean对象的afterPropertiesSet()初始化之后会调用AbstractBeanFactory.getObjectForBeanInstance()从JpaRepositoryFactoryBean工厂bean中执行getObject()返回创建的代理repository对象
详见 【源码】Spring Data JPA原理解析之Repository的自动注入一-CSDN博客 【源码】Spring Data JPA原理解析之Repository的自动注入二-CSDN博客 提醒最好指定Repository所在的包以免扫描整个SpringBoot启动类所在的包及其子包来获取Repository类 Repository接口实现原理
Repository在Spring容器中为代理对象Repository接口的接口方法有三种类型其实现原理分别为
11.1继承JpaRepositoryImplementation接口的接口方法
在Repository代理对象中target为SimpleJpaRepository对象。该对象实现了JpaRepositoryImplementation接口。
当执行JpaRepositoryImplementation接口中的方法时在动态代理中会调用执行SimpleJpaRepository的对应方法。
在SimpleJpaRepository中通过EntityManager接口及Criteria查询接口实现了对数据库的相关操作。
详见 【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码 11.2通过方法命名规则
通过方法命名规则自定义接口方法的实现是通过Repository代理对象中的QueryExecutorMethodInterceptor拦截器中实现的。
主要执行流程如下
1QueryExecutorMethodInterceptor方法拦截器的构造方法中会根据查询查找策略CreateIfNotFoundQueryLookupStrategy获得RepositoryQuery对象解析方法。对于按方法命名规则实现的方法使用的RepositoryQuery对象为PartTreeJpaQuery
2在PartTreeJpaQuery构造方法中创建一个PartTree对象解析方法名称中的起始关键字【如findBy、readBy、deleteBy等】、条件属性【实体类中的属性】、查询关键字【Between、In、Equals等】
3创建对应方法的countQuery和query将解析出的查询的基础信息封装在QueryPreparer对象中根据解析出的查询信息创建CriteriaQuery对象
4解析完方法信息保存在PartTreeJpaQuery后保存到QueryExecutorMethodInterceptor的MapMethod, RepositoryQuery queries中
5当Repository的接口被调用的时候在ReflectiveMethodInvocation.proceed()中先执行QueryExecutorMethodInterceptor.invoke()方法
5.1调用doInvoke()方法获取数据库执行后的数据
5.1.1调用RepositoryQueryMethodInvoker.invoke() - RepositoryQuery.execute() - AbstractJpaQuery.execute() - AbstractJpaQuery.doExecute() - JpaQueryExecution.execute() - JpaQueryExecution.doExecute()
5.1.2doExecute()是一个抽象方法针对不同的数据库查询返回值信息使用不同的实现类。所有的实现类都会先调用AbstractJpaQuery.createQuery()获取一个Query对象
5.1.3在AbstractJpaQuery.createQuery()中调用抽象方法doCreateQuery()。对于按方法命名规则的Repository接口实现类为PartTreeJpaQuery
5.1.4在PartTreeJpaQuery.coCreateQuery()方法中通过EntityManager.createQuery(criteriaQuery)返回TypedQuery然后执行invokeBinding()在TypedQuery对象中调用query.setParameter()绑定查询条件的参数值如果有分页设置分页信息
5.1.5参数完参数在6.1.3中设置hint等。然后执行6.1.2中的具体实现类执行数据库查询。如SingleEntityExecution实现类执行TypeQuery.getSingleResult()然后单个结果
5.2调用resultHandler.postProcessInvocationResult()对数据库查询后的值进行返回值类型转换
详见 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理一 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理二 11.3通过Query注解
通过Query注解添加SQL或HQL自定义接口方法的实现也是通过Repository代理对象中的QueryExecutorMethodInterceptor拦截器中实现的。对比方法命名规则的实现差异在于使用不同的查询解析方法。
主要执行流程如下
1QueryExecutorMethodInterceptor方法拦截器的构造方法中会根据查询查找策略CreateIfNotFoundQueryLookupStrategy获得RepositoryQuery对象解析方法。对于添加Query注解的方法使用的RepositoryQuery对象为SimpleJpaQuery和NativeJpaQuery
2SimpleJpaQuery和NativeJpaQuery都是继承AbstractStringBasedJpaQuery在AbstractStringBasedJpaQuery构造方法中解析对应的queryString和countQueryString生成DeclaredQuery对象实际对象为ExpressionBasedStringQuery。核心的解析过程在父类StringQuery中
3解析完方法信息保存在父类AbstractStringBasedJpaQuery后保存到QueryExecutorMethodInterceptor的MapMethod, RepositoryQuery queries中
4当Repository的接口被调用的时候在ReflectiveMethodInvocation.proceed()中先执行QueryExecutorMethodInterceptor.invoke()方法
4.1调用doInvoke()方法获取数据库执行后的数据
4.1.1调用RepositoryQueryMethodInvoker.invoke() - RepositoryQuery.execute() - AbstractJpaQuery.execute() - AbstractJpaQuery.doExecute() - JpaQueryExecution.execute() - JpaQueryExecution.doExecute()
4.1.2doExecute()是一个抽象方法针对不同的数据库查询返回值信息使用不同的实现类。所有的实现类都会先调用AbstractJpaQuery.createQuery()获取一个Query对象
4.1.3在AbstractJpaQuery.createQuery()中调用抽象方法doCreateQuery()。对于添加Query注解Repository接口实现类为SimpleJpaQuery或NativeJpaQuery方法实现在父类AbstractStringBasedJpaQuery.doCreateQuery()
4.1.4在AbstractStringBasedJpaQuery.doCreateQuery()方法中通过EntityManager.createQuery(queryString)返回Query【如果是NativeJpaQuery使用EntityManager.createNativeQuery(queryString)返回Query】然后执行invokeBinding()在Query对象中调用query.setParameter()绑定查询条件的参数值如果有分页设置分页信息
4.1.5参数完参数在6.1.3中设置hint等。然后执行6.1.2中的具体实现类执行数据库查询。如SingleEntityExecution实现类执行TypeQuery.getSingleResult()然后单个结果
4.2调用resultHandler.postProcessInvocationResult()对数据库查询后的值进行返回值类型转换
Auditing审计实现原理
JPA接口中提供了持久化的监听回调注解通过添加注解可以监听实体的新增、修改、删除的前后状态。
主要执行流程如下
1JPA的提供了持久化的监听回调注解
2Spring解析实体类时会解析实体类中添加的监听回调注解的监听器或者实体类中的EntityListeners注解中的监听器并归类存放在FastSessionServices中然后将FastSessionServices传给SessionImpl对象。对于Auditing监听器为AuditingEntityListener添加了PrePersist和PreUpdate在新增和修改之前回调。
3Auditing审计功能通过添加EnableJpaAuditing注解自动为AuditingEntityListener添加AuditHandler对象
4AuditHandler对象提供了对当前执行持久化对象的审计相关注解的属性获取、审计人获取
5JPA通过SessionImpl执行新增或修改操作时会调用FastSessionServices中对应操作类型的监听器从而执行AuditingEntityListener的方法
6AuditingEntityListener通过AuditHandler及当前的实体类通过反射为实体类的审计属性赋值
详见 【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理-CSDN博客 【源码】Spring Data JPA原理解析之Auditing执行原理-CSDN博客 JPA事务
12.1事务说明
事务是指在数据库管理系统中一系列紧密相关的操作序列这些操作作为一个单一的工作单元执行。事务的特点是要么全部成功要么全部失败不会出现部分完成的情况。如果事务中的任何一个操作失败那么整个事务都会被回滚到开始之前的状态以确保数据库的一致性和完整性。
事务的四个特性为原子性、一致性、隔离性和持久性。通常称为ACID。
在Spring框架中数据操作的事务是通过添加Transactional注解来实现的。
12.2JPA事务实现原理
JPA的Repository注入到Spring IOC容器的对象为代理对象其中添加了TransactionInterceptor拦截器在该拦截器中实现了事务。
主要执行流程如下
1当方法调用时执行TransactionInterceptor.invoke()方法该方法调用父类TransactionAspectSupport.invokeWithinTransaction()方法
2解析原方法的Transactional注解信息封装为TransactionAttribute对象
3从Spring容器中获取JpaTransactionManager对象
4根据传播特性选择性开启事务
5在try中执行ReflectiveMethodInvocation.proceed()方法直至执行原方法获取返回值
6在catch中捕获异常如果出现异常执行completeTransactionAfterThrowing()对满足回滚规则的执行回滚如果不满足回滚规则依然提交事务并抛出异常结束方法
7如果没有异常提交事务
详见 【源码】Spring Data JPA原理解析之事务注册原理-CSDN博客 【源码】Spring Data JPA原理解析之事务执行原理-CSDN博客 【源码】Spring事务之传播特性的详解-CSDN博客 12.3事务失效
事务使用不当时可能导致事务失效。常见的事务失效场景如下
1访问权限问题。非public访问权限的方法即使添加了Transactional注解事务无效
2无效异常。Spring事务回滚是通过异常捕获实现的默认只处理RuntineException或Error异常也可以通过Transactional的rollbackFor参数设置回滚异常
3业务异常捕获。如果在业务中捕获了异常Spring事务无法捕获到异常回滚失效。需要通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()设置回滚状态
4内部方法调用。在一个上下文没有事务的方法中通过this调用内部添加Transactional注解的方法时事务无效。因为此时的this是目标对象不是对应的代理对象
5传播特性使用不当。
6异步线程调用。事务信息是通过ThreadLocal保存在本地线程变量中对于异步线程无效
详见 【源码】Spring事务之事务失效及原理-CSDN博客 【源码】Spring事务之传播特性的详解-CSDN博客 JPA的优点与缺点
13.1优点
1简化数据持久化操作JPA框架提供了一系列的API和工具提供实体的CRUD方法减少SQL语句的编写开发效率高
2可移植性好JPA框架是基于对象关系映射ORM的规范底层采用Hibernate提供标注的查询语言对象化程度更好使得开发人员可以更加方便地切换不同的数据库
13.2缺点
1性能问题通过源码篇能够了解到JPA框架提供了较为复杂的对象关系映射机制可能会影响系统的性能
2灵活性较差JPA强调对象模型和数据库模型的映射对于复杂的SQL操作可能需要使用Criteria API或转为Native SQL
结尾
以上为本篇分享的全部内容。 关于本篇内容你有什么自己的想法或独到见解欢迎在评论区一起交流探讨下吧。