1.JdbcTemplate
a. JdbcTemplate是spring提供给我们的持久层操作工具类,tempalt是模板的意思。
b. maven依赖:spring-jdbc
c.依赖于DataSource,这里讲了个spring提供给我们的内置的DriverManagerDataSource(),但这个不是连接池,因为是new出来的,好的,通过spring容器创建就好
d. 使用JdbcTemplate进行CRUD操作:编不下去了,自己看吧,查询都用query方法,用BeanPropertyRowMapper<>()封装,返回的是list集合,
如果查询的是id,结果只能是有一个或者没有,就:
return accounts == null? null:accounts.get(0);
如果查询的是name,因为结果可能有多个,就:
if (accounts == null){
return null;
}else if (accounts.size() > 1){
throw new RuntimeException("查询结果不止一个");
}
e. 问题,每个dao层的类都要获取一遍jdbcTemplate,代码重复,我们考虑抽取出来定义一个类,然后让dao层的类都继承这个类,具体执行sql时,用super.getJdbcTemplate()获取。
其实,spring已经帮我们想到了,为我们提供了JdbcDaoSupport类,继承它就可以了,看一下JdbcdaoSupport的源码:
public abstract class JdbcDaoSupport extends DaoSupport {
@Nullable
private JdbcTemplate jdbcTemplate;
public JdbcDaoSupport() {
}
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = this.createJdbcTemplate(dataSource);
this.initTemplateConfig();
}
}
protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Nullable
public final DataSource getDataSource() {
return this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null;
}
public final void setJdbcTemplate(@Nullable JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.initTemplateConfig();
}
@Nullable
public final JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
大概是这个样子的:因为源码中我们不能标注注解,所以只能通过xml方式,配置accountService,为其注入dataSource,因为其继承了JdbcDaoSupport类,有dataSource的set方法,注入dataSource时,会判断JdbcTemplate是否为null,若为null,则走这行代码:
this.jdbcTemplate = this.createJdbcTemplate(dataSource);
调用createJdbcTemplate()方法,为jdbcTemplate初始化,我们在子类就可以直接通过super.getJdbctemplate(DataSource dataSource)方法获取到jdbcTemplate对象,综上,我们只需在xml配置文件中配置accountService,为其注入dataSource就ok了。
2.spring事务控制
引入:昨天的转账案例,我们是自定义一个事务管理类:TransactionManager,然后用创建了一个工厂类利用动态代理创建了代理对象,现在我们学了spring的aop之后,可以利用aop的方式取代工厂类,让spring帮我们实现动态代理。
回顾一下我们学的aop配置方式:
编写业务代码:service
编写增强代码:transactionManager
配置aop
<aop:config
<!--共性抽取配置切入点表达式-->
<aop:pointcut id="pt" value="execution(* cn.itcast.spring.service.impl.*.*(..))"></aop:pointcut>
<!--配置切面-->
<aop:aspect id="txManager" ref="transactionManager">
<aop:before method="begin" pointcut-ref="pt"></aop:before>
<aop:after-returning method="commit" pointcut-ref="pt"></aop:after-returning>
<aop:after-throwing method="rollback" pointcut-ref="pt"></aop:after-throwing>
<aop:after method="close" pointcut-ref="pt"></aop:after>
</aop:aspect>
</aop:config>
现在我们学习spring的事务控制,就不需要自己定义事务管理类了。
spring的事务控制:
a. PlatformTransactionManager平台事务管理器,用来管理事务的核心api,接口类型,其常用实现类是DataSourceTransactionManager。
b. TransactionDefinition 事务的定义对象,定义了事务的相关属性
-String getName() 获取事务对象名称
-int getIsolationLevel 获取事务隔离级别
-int getPropagationBehavior 获取事务传播行为
-int getTimeOut 获取事务超时时间
-boolean isReadOnly 获取事务是否只读
c. TransactionStatus 事务的状态描述对象(了解,我们暂时涉及不到)
spring的声明式事务控制之xml配置方式
<!--这里的id或者name建议按照规范写,因为我们是有经验的开发人员-->
a. 声明事务管理类
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<properties name="dataSource" ref="dataSource"></properties>
</bean>
b.配置事务通知
<tx:advice id="txManager" transactionManager="transactionManager">
<tx:attribute>
<!--给每一需要绑顶事务的方法配置,我们使用*通配的方式,所以要求我们方法名要规范-->
<!--增删改操作配置,一定绑定事务,可进行读写-->
<tx:method name="*" propagation="REQUIRED" read-only="false">
<!--查询操作配置,不一定绑定事务,只能刻度-->
<tx:method name="find*" propagation="REQUIRED" read-only="false">
</tx:attribute>
</tx:advice>
xxxxxxxxxx 事务的属性配置:这段我拷贝过来,常用的就是propagation和read-only<tx:attributes> <!-- 指定方法名称:是业务核心方法
read-only:是否是只读事务。默认 false,不只读。
isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。propagation:指定事务的传播行为。
timeout:指定超时时间。默认值为:-1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。
-->
<tx:method name="*" read-only="false" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
c. 配置切面
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="pt" expression="excution(* cn.itcast.spring.service.impl.*.*(..)">
<!--建立切入点表达式和事务通知的关系-->
<aop:advisor advice-ref="txManager" pointcut-ref="pt">
</aop:config>
spring的声明式事务控制之注解配置方式
a. 声明事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<properties name="dataSource" ref="dataSource"></properties>
</bean>
b.开启spring是事务控制的注解支持
<tx:annotation-driver transaction-manager="transactionManager"/>
c.在要使用注解的类或方法上使用@Transaction注解
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
注意这里事务属性会对该类的所有方法生效,如果是增删改方法,需要在单独配置:
@Transactional(peopagation = Propagation.REQUIRED,readOnly = false)
spring的声明式事务控制之注解配置方式简单但不灵活,xml配置方式稍微复杂,但一劳永逸。
spring的全注解事务控制方式:
如何取代xml配置文件这个读取容器入口,前面我们学过定义一个配置类,传递给AnnotionConfigApplicationContext这个容器类,使用到的标签有@Configuration,@ComponentScan,@Import,@PropertySource,@Bean,@Value等
今天在学一个开启spring对事务注解方式的支持,@EnableTransactionManagement
使用在主配置类上即可。
spring暂时告一段落,主要学习了IoC,DI,AOP,事务控制,JdbcTemplate,有点啥都不会的感觉,也许以后写项目会一直用到,使用起来会好点,但是具体的原理要知道一点,比如:
IoC: 控制反转,原理:反射
DI: 依赖注入,为容器中对象的属性赋值
AOP: 面向切面编程,对已有功能进行无代码侵入增强
事务控制:依赖于AOP
JdbcTemplate:依赖于DataSource
配置文件多写应该会熟练吧。