Spring入门(三)— AOP注解、jdbc模板、事务
2018-02-19 23:03
453 查看
一、AOP注解开发
导入jar包aop联盟包、 aspectJ实现包 、 spring-aop-xxx.jar 、 spring-aspect-xxx.jar
导入约束
aop约束
托管扩展类和被扩展类
<!-- 要做AOP, 一定要托管扩展类和被扩展类 --> <bean id="us" class="com.pri.service.impl.UserServiceImpl"></bean> <bean id="logger" class="com.pri.util.Logger"></bean>
也可以使用注解来托管这两个类 。 @Component
在扩展出来的功能类身上和方法上打注解
@Aspect //这个注解,是和aop有关,用于表示该类是一个功能扩展类,专门用来做增强的。 public class Logger { @Before("execution(* com.pri.service.impl.*.*(..))") public void log(){ System.out.println("输出日志了~~~!"); } }
二、 Jdbc模板
为什么spring也要提供jdbc模板呢?spring是属于service层的框架, 它所处的位置比较尴尬,并且它想让自己更受程序员的喜爱。 除了能够做好自己的核心
IOC&
AOP, 它还对前后两个框架都提供了支持。 spring其实对dao层的大部分技术有提供模板支持 。
1. jdbc模板的入门
public void testDemo(){ //数据源,连数据库。 连什么类型的数据, 哪个库, 账号 & 密码 DriverManagerDataSource dataSource =new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///stus"); dataSource.setUsername("root"); dataSource.setPassword("root"); //1. 创建jdbc模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); String sql = "insert into t_user values(null , ? , ? )"; //2. 执行添加操作,其实它的用法和以前的queryrunner一样。 jdbcTemplate.update(sql , "66666","zhangsan"); }
2. crud操作
insertString sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql, "heima24","6666");
delete
@Test public void testDelete(){ //3. 执行添加操作 String sql = "delete from t_user where uid = ?"; jdbcTemplate.update(sql, 11); }
udpate
@Test public void testUpdate(){ //3. 执行添加操作 String sql = "update t_user set password=? where uid=?"; jdbcTemplate.update(sql, "888",11); }
findCount
@Test public void testFindCount(){ //3. 执行添加操作 String sql = "select count(*) from t_user"; int count = jdbcTemplate.queryForObject(sql, Integer.class); System.out.println("count="+count); }
findObject
@Test public void testFindObject(){ //3. 执行添加操作 String sql = "select * from t_user where uid = ?"; User user = jdbcTemplate.queryForObject(sql,new MyRowMapper() , 10); System.out.println("user="+user); }
findList
@Test public void testFindList(){ //3. 执行添加操作 String sql = "select * from t_user "; List<User> user = jdbcTemplate.query(sql, new MyRowMapper()); System.out.println("user="+user); }
查询要求我们手动封装class MyRowMapper implements RowMapper<User>{
@Override public User mapRow(ResultSet rs, int arg1) throws SQLException { System.out.println("arg1=="+arg1); User user = new User(); user.setUid(rs.getInt("uid")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); return user; } }
3. jdbc模板的注入写法
该小节演练的是三层结构的所有属性注入写法。(不写action | servlet)
1. 分析
以下代码其实是位于dao层的@Override public void save(User user) { // 数据源,连数据库。 连什么类型的数据, 哪个库, 账号 & 密码 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///stus"); dataSource.setUsername("root"); dataSource.setPassword("root"); // 1. 创建jdbc模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); String sql = "insert into t_user values(null , ? , ? )"; // 2. 执行添加操作,其实它的用法和以前的queryrunner一样。 jdbcTemplate.update(sql, user.getPassword(), user.getUsername()); }
这套代码很多,而且它只是一个dao的操作代码而已。 如果我们还有别的dao方法。也要执行数据库操作,那么必然也得写出来这样的代码。 那么就存在冗余代码了。
解决方案:
以前的解决方法:
工具类 | 静态代码块
现在学了spring了,我想用spring的手法来简化dao的这一套代码。
分析以上代码,其实它就是做了两个工作。
a. 创建了jdbc模板的对象,并且完成了属性的赋值工作。
b. 创建了dataSource 的对象,并且完成了属性的赋值工作。
spring也可以完成这个工作, 创建对象,其实就是`IOC`的体现, 对属性的赋值工作其实就是`DI`的体现
•~~~xml <bean id="jdbctemplate" class=""> <property name="dataSource" ref="dataSource"> <bean id="dataSource" class=""> <property name="..." value=""> <property name="..." value=""> <property name="..." value=""> <property name="..." value=""> •~~~
2. 基本实现
servicepublic class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { System.out.println("调用了UserServiceImpl的save方法~~!"); userDao.save(); } }
dao
public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override public void save() { System.out.println("调用了UserDaoImpl的save方法~~"); //3. 执行添加操作 String sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql, "heima242","0000"); } }
xml
<bean id="us" class="com.pri.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> <bean id="userDao" class="com.pri.dao.impl.UserDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///stus"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>
3. 整合c3p0连接池
导入jar包c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
在xml中配置
没有使用c3p0连接池的配置 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///user"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> 使用了c3p0的配置 <!-- 使用c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///user"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean>
4. 使用jdbc.properties记录数据库连接信息
为了方便修改数据库连接信息,通常在src下使用properties文件来记录他们。主要是方便修改
在src下新建一个properties文件,内容如下 名:jdbc.properties
driverClass=com.mysql.jdbc.Driver jdbcUrl=jdbc:mysql:///user user=root password=root
在xml里面导入jdbc.properties ,并且在dataSource里面引用
a. 导入context约束 b. 导入jdbc.properties <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 使用c3p0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${driverClass}"></property> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> </bean>
三、 事务管理
1. 事务的回顾
什么事务,事务有什么用?事务是用于包装一组操作的。当这一组操作里面的所有步骤都执行成功,那么这一组操作就算成功(事务的提交),如果有哪一个步骤执行失败,那么这一组操作就以失败告终。(事务的回顾)
事务的特性
原子性、
一致性、
隔离性、
持久性
如果不考虑隔离级别,那么事务并发会出现以下问题
读的问题
脏读 : 读到了另一个事务还没有提交的数据
不可重复读 : 读到了另一个事务已经提交的数据 (针对的是update的数据)
虚读| 幻读 : 读到了另一个事务已经提交的数据(针对的是insert的数据)
解决方案: 设置隔离级别
读未提交
读已提交 Oracle
可重复读 MySql
序列化|串行化
写的问题
丢失更新: 最后操作的事务,不管是提交还是回滚,都会让前一个是的数据丢失掉。
解决方案:
悲观锁 : 还没开始就认为一定会丢失更新。
每一个事务在执行操作之前,先进行一次查询。 并且查询的语句里面带有关键字
for update
乐观锁 : 认为不会出现丢失更新,
要求程序员手动控制,给表额外添加一个字段 如: version。
2. Spring对事务的管理办法
事务应该写在哪一层? 为什么spring也要插手管理事务?事务应该写在Service层。 因为service表示的业务,一组业务可能会执行多个到的方法。所以在Service层声明事务更好一点。 而且spring正好是Service层的解决方案。
Spring针对事务的管理API
Spring 可以管理事务, 但是真正完成操作的技术,spring可不管。 dao层使用的技术可能有很多。
jdbc、
hibernate、
mybatis. 但是这几个框架,他们开启事务的办法,可能不一样。 spring为了统一管理事务,声明了一套规范出来,并且对底下的使用频率比较到的技术,都给出了具体的实现。
管理事务的规范是 : PlatformTransactionManager jdbc | mybatis : DataSourceTransactionManager hibernate : HibernateTransactionManager
spring对dao层使用什么技术,它不管,它统一规定,要操作事务,必须使用管理员!!!
3. spring对事务支持的写法
提供了三种写法
编程式事务、
声明式事务(xml & 注解)
1. 编程式事务
纯靠写代码来完成事务配置
@Test public void test(){ //事务的管理员是用来管理事务的,包含了打开事务、 提交事务、 回滚事务 final DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///stus"); dataSource.setUsername("root"); dataSource.setPassword("root"); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); //1. 创建事务的模板对象。 TransactionTemplate transactionTemplate = new TransactionTemplate(); transactionTemplate.setTransactionManager(transactionManager); //事务事务的模板对象 transactionTemplate.execute( new TransactionCallback<Object>() { //在事务里面执行这个方法。 @Override public Object doInTransaction(TransactionStatus arg0) { //添加操作 JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); String sql = "insert into t_user values ( null , ? , ?)"; jdbcTemplate.update(sql, "123","王五"); int a = 1 / 0 ; jdbcTemplate.update(sql, "6666","赵六"); return null; } }); }
2. 声明式事务(xml)
xml方式配置事务,其实就是使用AOP的思想,在方法执行前,开启事务,方法执行后,提交事务(回滚事务)
<!-- 以下属于事务的配置 如果要用事务了,那么事务的管理员是谁啊。 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="advice01" transaction-manager="transactionManager"> <tx:attributes> <!-- 对前面的表达式找到的那一堆方法,进行过滤配置,表示谁才能用事务管理, 如果是* ,表示前面找到的那一堆都用事务管理 --> <tx:method name="save*"/> <tx:method name="update*"/> <tx:method name="delete*"/> </tx:attributes> </tx:advice> <!-- 以上配置,到目前为止,只是说明了,如果要开启事务,管理员是谁。 但是缺少了一个东西。 就是哪一个方法到底要用事务呀? --> <aop:config> <aop:pointcut expression="execution(* com.pri.service.impl.*.*(..))" id="aa"/> <aop:advisor advice-ref="advice01" pointcut-ref="aa"/> </aop:config>
3. 声明式事务(注解)
使用注解的方式来开启事务
xml配置
1. 在xml中 声明注解事务的管理员 <!-- 以下属于事务的配置 如果要用事务了,那么事务的管理员是谁啊。 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 指定注解事务使用的管理员是谁 --> <tx:annotation-driven transaction-manager="transactionManager"/>
代码配置
2. 在业务逻辑类上或者方法上打注解 类上的注解,表示类中的所有方法都用事务, 如果在方法上打注解,表示只有这个方法才会用事务
@Transactional public class UserServiceImpl implements UserService { } public class UserServiceImpl implements UserService { @Transactional @Override public void save() {} }
相关文章推荐
- Day49-Spring-03 - AOP开发(注解方式)-JDBC模板- 事务管理
- Spring框架的第三天(AOP注解方式、JDBC模板、事务管理)
- spring----AOP注解以及spring的JDBC和事务
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- 第四天AOP注解的方式以及spring的JDBC模板
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- (9) 使用Spring的注解方式实现AOP入门 以及 细节
- 【Spring】spring-mvc hibernate druid jdbc等数据源事务配置详解(解决注解事务不生效问题)
- spring aop 注解 事务管理 以及各种参数分析
- spring 整合JDBC和AOP事务的方法
- 注解开发spring-aop 入门
- 【Spring】在Spring框架下使用注解配置JDBC事务
- Spring注解+AOP+JDBC
- 【SSH】Spring学习(三)Spring整合JDBC、Spring中AOP事务
- Spring 注解AOP 入门
- Web框架梳理:第四章:Spring学习入门、Spring属性注入、AOP编程、注解开发
- Spring学习历程---使用注解方式入门AOP
- spring aop 注解入门
- spring 2.5整合jdbc进行数据库操作和注解事务控制
- SpringAOP入门例子-通过注解