使用SpringDataJPA
的时候,总是会遇到一些复杂的查询情况,比如说需要按照传入的参数拼装SQL
,如果参数为null
就不拼装这段SQL
,并且同时还要使用数据库中的自定义函数来辅助完成查询时的计算,这个时候用JpaSpecification
都已经无法解决问题了,就算在Repository
实体类上使用@Query
注解来规定死查询语句,那么判断参数为null
或者空字符串也要做很多工作,可能会使用很多的IF()
函数,这就让SQL
的可读性变得更加差劲。
所以这个时候需要尽量回归原生,使用JdbcTemplate
,但是一定要避免SQL
注入攻击,还要拥有JPA
那样的SQL
参数(例如::username
),所以总结一下正确的JdbcTemplate
的使用方式。
使用JdbcTemplate
Spring
提供了两种JdbcTemplate
:
org.springframework.jdbc.core.JdbcTemplate
普通的JdbcTemplate
org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
可以传递具名参数的JdbcTemplate
,例如::username
使用XML配置JdbcTemplate
如果数据层有很多的类,每个类都需要JdbcTemplate
,那么需要使用XML
为每个类都注入一个JdbcTemplate
,这就相当的费事了,Spring
提供了一个JdbcDaoSupport
类,可以让数据层来继承,类中提供了一个getJdbcTemplate()
方法,可以直接获取JdbcTemplate
,这就解决了数据层每个类都要注入一个JdbcTemplate
的问题。
对于事务的补充说明
关于事务的隔离级别,网上的教程特别的多了,就不总结了。
Spring
也提供了对于隔离级别的支持:
ISOLATION_DEFAULT
:默认级别,用数据库默认的级别ISOLATION_READ_UNCOMMITTED
:可以读取未提交的数据ISOLATION_READ_COMMITTED
:只能读取已经提交的数据,解决了脏读的问题ISOLATION_REPEATABLE_READ
:是否读取其他事务修改提交后的数据,解决不可重复读的问题ISOLATION_SERIALIZABLE
:是否读取其他事务添加提交后的数据,解决幻读的问题
Spring
也提供了事务的传播行为:
REQUIRED
:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)SUPPORTS
:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)MANDATORY
:使用当前的事务,如果当前没有事务,就抛出异常REQUERS_NEW
:新建事务,如果当前在事务中,把当前事务挂起。NOT_SUPPORTED
:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起NEVER
:以非事务方式运行,如果当前存在事务,抛出异常NESTED
:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED
类似的操作。
同时也提供了超时时间,如果设置为-1
就是没有限制,以秒为单位。
提供了设置是否为只读事务,查询的时候开启就可以了。
XML
文件的概述如下
tx:advice
:标签 用来配置事务增强
id
:事务增强的唯一标识transaction-manager
:事务管理类实例,比如说DataSourceTransactionManager
tx:advice
拥有子标签tx:attributes
tx:attributes
的子标签tx:method
的属性
read-only
:是否是只读事务。默认false
,不只读。isolation
:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。propagation
:指定事务的传播行为。timeout
:指定超时时间。默认值为:-1
。永不超时。rollback-for
:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。no-rollback-for
:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回 滚。没有默认值,任何异常都回滚。
若要开启事务,需要配置AOP
<!-- 配置 aop -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(* com.cy.service.*.*(..))" id="transactionPointcut"/>
<!-- 建立事务的通知和切入点表达式的关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/>
</aop:config>
若要使用注解
// 作用在方法,类,接口上,优先级:方法 > 类 > 接口
@Transactional(readOnly=true, propagation=Propagation.SUPPORTS)
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
// 允许使用事务管理,SpringBoot项目不用写
@EnableTransactionManagement