一、spring-Jdbc
JdbcTemplate
JdbcTemplate主要提供以下五类方法:
execute方法:
可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:
update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:
用于执行查询相关语句;
call方法:
用于执行存储过程、函数相关语句。
LobHandler和LobCreator
使用:
将LobHandler 加入到ioc容器当中
@Bean("lobHandler")
public LobHandler createLobHandler(){
return new DefaultLobHandler();
}
jdbcTemplate.execute("insert into userinfo(id,image,description)values(?,?,?)", new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
@Override
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, DataAccessException {
ps.setInt(1,3);
//保存图片的二进制数组数据
lobCreator.setBlobAsBytes(ps, 2,userinfo.getImages() );
//保存描述的字符串数据
lobCreator.setClobAsString(ps,3,userinfo.getDescription());
}
});
NamedParameterJdbcTemplate
在原本JdbcTemplate的基础上把使用?当作占位符改为使用具名参数替代。
具名参数:
( SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名
参数由框架类在运行时用占位符取代)
在NamedParameterJdbcTemplate里面封装了一个JdbcTemplate对象,只不过把它看成了接口类型JdbcOperations。所以NamedParameterJdbcTemplate可以使
用全部jdbcTemplate方法。
使用:
将NamedParameterJdbcTemplate 加入到ioc容器当中
@Bean
public NamedParameterJdbcTemplate createNamedJdbcTemplate(JdbcTemplate
jdbcTemplate){
return new NamedParameterJdbcTemplate(jdbcTemplate);
}
@Test
public void testMethod(){
Map<String,Object> map=new HashMap<>();
map.put("id",1);
map.put("username","szu");
map.put("passwoed","niuBi");
jdbcTemplate.execute("insert into sys_user values(:id,:username,:password) ",map);
}
把原来的占位符?改为冒号(:)加上字段名字。
由于赋值是按照字段名来找的,所以顺序是可以随意的。
使用BeanMap
@Test
public void testMethod(){
BeanMap beanMap=BeanMap.create(user)
jdbcTemplate.execute("insert into sys_user values(:id,:username,:password) ",beanMap);
}
二、spring-Transaction
1、spring事务当中重要接口
PlatformTransactionManager
作用:
此接口是Spring的事务管理器核心接口。Spring本身并不支持事务实现,只是负责提供标准,应用底层支持什么样的事务,需要提供具体实现类。此处也是策略模式的具体应用。在Spring框架中,也为我们内置了一些具体策略,例如:DataSourceTransactionManager,HibernateTransactionManager,
JpaTransactionManager,JtaTransactionManager等等。
(JpaTransactionManager和HibernateTransactionManager事务管理器在spring-orm包中)
源码:
public interface PlatformTransactionManager {
//事务状态信息
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
//提交
void commit(TransactionStatus var1) throws TransactionException;
//回滚
void rollback(TransactionStatus var1) throws TransactionException;
}
TransactionDefinition
此接口是Spring中事务可控属性的顶层接口,里面定义了事务的一些属性以及获取属性的方法。例如:
事务的传播行为,事务的隔离级别,事务的只读,事务的超时等等。通常情况下,我们在开发中都可以配置这些属性,以求达到最佳效果。配置的方式支持xml和注解。
源码:
public interface TransactionDefinition {
/*如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
一般的选择(默认值)
*/
int PROPAGATION_REQUIRED = 0;
//支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
int PROPAGATION_SUPPORTS = 1;
//使用当前的事务,如果当前没有事务,就抛出异常
int PROPAGATION_MANDATORY = 2;
//新建事务,如果当前在事务中,把当前事务挂起。
int PROPAGATION_REQUIRES_NEW = 3;
//以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
int PROPAGATION_NOT_SUPPORTED = 4;
//以非事务方式运行,如果当前存在事务,抛出异常
int PROPAGATION_NEVER = 5;
//如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作
int PROPAGATION_NESTED = 6;
//事务的隔离级别默认值,当取值-1时,会采用下面的4个值其中一个。
int ISOLATION_DEFAULT = -1;
/**
* 事务隔离级别为:读未提交
* 执行效率最高,但什么错误情况也无法避免
*/
int ISOLATION_READ_UNCOMMITTED = 1;
/**
* 事务隔离级别为:读已提交
* 可以防止脏读的发生,但是无法防住不可重复读和幻读的发生
*/
int ISOLATION_READ_COMMITTED = 2;
/**
* 事务隔离级别为:可重复读
* 可以防止脏读和不可重复读的发生,但是无法防住幻读的发生
*/
int ISOLATION_REPEATABLE_READ = 4;
/**
* 事务隔离级别为:串行化
* 此时所有错误情况均可防住,但是由于事务变成了独占模式(排他模式),因此效率最低
*/
int ISOLATION_SERIALIZABLE = 8;
//超时限制。默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
@Nullable
String getName();
}
TransactionStatus
此接口是事务运行状态表示的顶层接口,里面定义着获取事务运行状态的一些方法。
public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();//是否一个新的事务
boolean hasSavepoint();//是否包含存储点
void setRollbackOnly();//设置事务回滚
boolean isRollbackOnly();//是否是只回滚事务
@Override
void flush();//刷新事务
boolean isCompleted();//事务是否已经完成(标识就是提交或者回滚了)
}
2、声明事务控制
@EnableTransactionManagement
作用:
此注解是Spring支持注解事务配置的标志。表明Spring开启注解事务配置的支持。是注解驱动开发事务配置的必备注解。
源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* true:基于目标类代理。(第三方cglib)
* false:基于接口代理。(jdk官方Proxy)
*/
boolean proxyTargetClass() default false;
/**
* 指定事务通知是如何执行的。
* AdviceMode.PROXY:类运行期代理
* AdviceMode.ASPECTJ:类加载时代理
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 指示在切面类中有多个通知时事务处理的执行顺序。
* 效果同@Order
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
@Transactional
此注解是Spring注解配置事务的核心注解,无论是注解驱动开发还是注解和XML混合开发,只有涉及配置事务采用注解的方式,都需要使用此注解。
通过源码我们看到,该注解可以出现在接口上,类上和方法上。
分别表明:
接口上:当前接口的所有实现类中重写接口的方法有事务支持。
类上:当前类中所有方法有事务支持。
方法上:当前方法有事务的支持。
优先级:
方法上>类上>接口上。
源码:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
*指定事务管理器的唯一标识,也就是指定id
*/
@AliasFor("transactionManager")
String value() default "";
//同value
@AliasFor("value")
String transactionManager() default "";
// 指定事务的传播行为
Propagation propagation() default Propagation.REQUIRED;
//事务的隔离级别
Isolation isolation() default Isolation.DEFAULT;
//事务的超时时间
int timeout() default -1;
//事务是否只读
boolean readOnly() default false;
// 通过指定异常类的字节码,限定事务在特定情况下回滚
Class<? extends Throwable>[] rollbackFor() default {};
//通过指定异常类的全限定类名,限定事务在特定情况下回滚
String[] rollbackForClassName() default {};
// 通过指定异常类的字节码,限定事务在特定情况下不回滚
Class<? extends Throwable>[] noRollbackFor() default {};
// 通过指定异常类的全限定类名,限定事务在特定情况下不回滚
String[] noRollbackForClassName() default {};
}
注解驱动事务控制
1.配置TransactionManagement实现类
public class TransactionConfig(){
@Bean
public PlatformTransactionManager createTransactionManagement(DataSource dataSource){
return new DataSourceTransactionManager();
}
}
2.开启事务控制并导入配置类
@Configuration
@Import(TransactionConfig.class)
@EnableTransactionManagement//开启事务控制
public class SpringConfiguration {
}
3.业务层接口添加@Transactional注解
注意:事务控制一般声明在业务层,一方面是业务层接口一般会出现多次请求调用持久层中的方法,更容易发生错误,而持久层当中方法一般只会请求一次数据库。
另一方面是一般当我们使用持久层框架开发(如mybatis)的时候,持久层的方法实现都是通过动态代理实现的,无法通过编码添加事务。
@Service("userService")
//@Transactional 注解添加在类上时,表明这个类上所有的方法都添加事务控制
public class UserServiceImpl implements UserService {
@Transactional
public void save(User user){}
}
3.配置TransactionManagement实现类
public class TransactionConfig(){
public PlatformTransactionManager createTransactionManagement(DataSource dataSource){
return new DataSourceTransactionManager();
}
}
3、编程式事务控制-TransactionTemplate
1.将TransactionTemplate 加入ioc容器
public class TransactionConfig(){
@Bean
public PlatformTransactionManager createTransactionManagement(DataSource dataSource){
return new DataSourceTransactionManager();
}
@Bean
public TransactionTemplate createTransactionTemplate(PlatformTransactionManager pTM){
return TransactionTemplate(pTM) ;
}
}
@Service("userService")
//@Transactional 注解添加在类上时,表明这个类上所有的方法都添加事务控制
public class UserServiceImpl implements UserService {
@AutoWired
privated TransactionTemplate transactionTemplate;
public void save(User user){
transactionTemplate.execute(new TransactionCallBack<Object>(){
@override
public Object doTransaction(TransactionStatus status){
//TODO---
return null;
}
})
}
}
@TransactionEventListener
用于配置一个事务的事件监听器。使我们在事务提交和回滚前
后可以做一些额外的功能。例如:对事务执行监控,执行中同步做一些操作等等。
源码:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EventListener
public @interface TransactionalEventListener {
/**
* 指定事务监听器的执行是在何时。
* 取值有:
* 事务提交之前
* 事务提交之后 默认值
* 事务回滚之后
* 事务执行完成之后
*/
TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;
// 若没有事务的时候,对应的event是否已经执行 默认值为false表示 没事务就不执行了
boolean fallbackExecution() default false;
//指定事件类的字节码
@AliasFor(
annotation = EventListener.class,
attribute = "classes"
)
Class<?>[] value() default {};
@AliasFor(
annotation = EventListener.class,
attribute = "classes"
)
Class<?>[] classes() default {};
// 用于指定执行事件处理器的条件。取值是基于Spring的el表达式编写的。
String condition() default "";
}
使用:
1.定义事件类,继承ApplicationEvent类并实现一个MyApplicationEvent(Object source )构造方法。
public class MyApplicationEvent extends ApplicationEvent {
//TODO---
public MyApplicationEvent(Object source ) {
super(source);
//TODO---
}
}
2.定义监听器类
@Component//将该类加入ioc容器
public class MyTransactionEventListener {
//事务提交之后执行下面方法
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void doSomething(MyApplicationEvent event){
}
}
3.定义事件发布类,确定事件发布的具体位置及操作
@Service("userService")
@Transactional
public class UserServiceImpl implements userService {
@Autowired//事件发布类,也就是事件源,该类在解析注解时已加入到ioc容器当中
private ApplicationEventPublisher applicationEventPublisher;
public void save(){
try{
try{
//TODO
applicationEventPublisher.publishEvent(obj);
//TODO
}finally{
//TODO
//applicationEventPublisher.publishEvent(obj);
//TODO
}
}catch(Exception e){
//TODO
//applicationEventPublisher.publishEvent(obj);
//TODO
}
}
}
TransactionSynchronizationManager*
事务的同步管理器类,实现连接和线程绑定从而控制事务的核心类
它是个抽象类,但是没有任何子类 因为它所有的方法都是静态的
DataSourceUtils*
spring中数据源的工具类。
里面定义着获取连接的方法
实现连接与线程绑定:
@Bean("connection")
public Connection getConnection(DataSource dataSource){
TransactionSynchronizationManager.initSynchronization() ;
Connect connect=DataSourceUtils.getConnect(dataSource);
return connect;
}
要求理解源码。