Day49-Spring-03 - AOP开发(注解方式)-JDBC模板- 事务管理
2017-08-12 15:40
666 查看
一、AOP注解(注解方式)
在Spring02中讲述了xml方式的aop,现在讲解aop的注解形式。
导入jar包
四个基本包
Spring包下:spring-aop-4.2.9.RELEASE.jar,spring-aspects-4.2.9.RELEASE.jar
相关jar包:aopalliance-1.0.jar,aspectjweaver-1.8.9.jar
(和aop的xml方式导入的jar包一样)
导入约束
导入AOP的约束
在xml中打开aop的自动代理开关,同时增强类和业务逻辑类也是必须的
如果是IOC的注解,采用context:component-scan来打开
如果是AOP的注解:采用aop:aspectj-autoproxy
<bean id="us" class="com.itheima.service.impl.UserServiceImpl" ></bean> <bean id="logger" class="com.itheima.util.Logger" ></bean> <!-- 扫描开关打开有两种: 如果是IOC的注解, 采用context : conponent-scan 开关去打开 如果是AOP的注解 , 采用aop: aop:aspectj-autoproxy --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
在增强类中打上注解。
@Aspect //表示我们这个Logger类是一个切面增强类。 public class Logger { @Before("execution(* com.itheima.service.*.*(..))") public static void log(){ System.out.println("输出日志了~~"); } }
二、 JDBC模板
Spring 由于所处的位置比较尴尬,刚好处在三层的中间位置。 它除了弄好自己的IOC + AOP之外, 为了更好的推广自己,让自己的生命力变得更持久, 也对持久层的框架做出了支持。 说白了,就是包装了dao层的框架代码。让程序员编程效率更高点。对持久化框架的支持有以下几个 如果dao层采用的是JDBC来实现,那么spring会提供 JDBC模板 如果dao采用的是hibernate来实现,那么spring也会随之提供hibernate模板 Mybatis也是如此..
1. jdbc模板 入门 – 以向数据库插入数据为例子
导入jar包额外导入 三个jar包
spring-jdbc-xxx.jar
spring-tx-xxx.jar (事务的包)
jdbc的驱动包
写代码
如何写这段代码:
只需要记住一个关键的类名:JdbcTemplate即可,后续可以通过这个类,添加响应的dataSource,然后进行插入
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///user"); dataSource.setUsername("root"); dataSource.setPassword("root"); //1. 创建jdbc模板实例 和dbutils挺像的。 操作数据库,也是两个方法。 JdbcTemplate jdbcTemplate = new JdbcTemplate(); //设置数据源 jdbcTemplate.setDataSource(dataSource); String sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql, "admin","admin");
2. jdbc模板 CRUD
jdbc模板针对查询的操作,稍微要注意下即可,需要我们手动封装数据。insert
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///user"); dataSource.setUsername("root"); dataSource.setPassword("root"); //1. 创建jdbc模板实例 和dbutils挺像的。 操作数据库,也是两个方法。 JdbcTemplate jdbcTemplate = new JdbcTemplate(); //设置数据源 jdbcTemplate.setDataSource(dataSource); String sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql, "admin","admin");
delete
@Test public void test01(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); //dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db_for_test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "delete from user where id = ?"; jdbcTemplate.update(sql, 6); }
update
@Test public void test02(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); //dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db_for_test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //String sql = "insert into user values(null,?,?)"; String sql = "update user set address = ? where id = ?"; jdbcTemplate.update(sql,"地球",5); }
查询总条数 - 稍微麻烦一点,功能没有JDBC强,勉强可用
JdbcTemplate这个类进行查询的时候,不会将结果封装成为我们需要的对象,需要我们手动进行封装
查询总记录条数
@Test public void test03(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); //dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db_for_test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "select count(*) from user"; int result = jdbcTemplate.queryForObject(sql, Integer.class); System.out.println(result); }
查询单个对象
@Test public void test04(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); //dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db_for_test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "select * from user where id = ?"; User result = jdbcTemplate.queryForObject(sql, new MyRowMapper(),5); System.out.println(result); } class MyRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet paramResultSet, int paramInt) throws SQLException { int id = paramResultSet.getInt("id"); String name = paramResultSet.getString("name"); String address = paramResultSet.getString("address"); User user = new User(); user.setAdd(address); user.setName(name); return user; } }
查询list集合
为什么不用jdbcTemplate.queryforList()方法呢?因为里面没有RowMapper这个参数
@Test public void test04(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); //dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db_for_test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "select * from user"; List<User> list= jdbcTemplate.query(sql, new MyRowMapper()); System.out.println(list); } class MyRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet paramResultSet, int paramInt) throws SQLException { int id = paramResultSet.getInt("id"); String name = paramResultSet.getString("name"); String address = paramResultSet.getString("address"); User user = new User(); user.setAdd(address); user.setName(name); return user; } }
3. jdbc模板 注入写法 – 使用测试整合UserService - UserDao - JDBCTemplate - C3p0连接池
导包:导入Spring四个核心jar包,Spring-jdbc-xx.jar ,Spring-tx-xxx.jar, jdbc驱动, Spring-test-xxx.jar
测试类:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class testSpring模板整合service层和dao层 { @Autowired private UserService userService; @Test public void test01(){ userService.save(); } }
service代码
@Service public 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() { String sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql, "zhangsan","123456"); System.out.println("保存完毕~"); } }
配置
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" scope="prototype"> <property name="userDao" ref="userDao"></property> </bean> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <!-- ref : 告诉spring要new哪一个类给注入进去 要想表示这个类, 得声明一个bean --> <property name="jdbcTemplate" ref="jt"></property> </bean> <bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="ds"></property> </bean> <bean id="ds" 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>
4. jdbc模板 关联c3p0连接池
优化使用:使用c3p0来优化上面案例的模板的使用代码不用改动,只要改动注入的数据源即可
首先导入c3p0连接池的jar包
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> <bean id="userDao" class="com.itheima.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="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_for_test"></property> <property name="user" value="root"></property> <property name="password" value="123456"></property> </bean> <context:component-scan base-package="com.itheima"></context:component-scan> </beans>
三、事务
什么是事务事务其实就是用来包装一组逻辑,控制逻辑的整体结果。 如果这一组逻辑里面有一个动作执行失败, 那么整组的结果就以失败告终。(回滚事务) , 如果这一组逻辑里面运行都成功了,那么就认为成功(提交事务)
事务特性
ACID 原子性 、一致性、隔离性、 持久性
事务如果不考虑隔离会出现以下问题
读问题
脏读
不可重复读
虚读|幻读
隔离级别:
读未提交
读已提交 : Oracle
可重复读 : Mysql
序列化|串行化
写问题
丢失更新
两个事务同时操作。 不管后面的那个事务是提交还是回滚,都将让前一个事务提交的结果,失效。丢失。
乐观锁
认为不会出现丢失更新, 要在表里面加一个字段,自己维护。
悲观锁
还没开始做,就认为一定会丢失更新。
在开始操作之前,先执行查询 for update
1. 编程式
导包:Spring-jdbc-XXX.jar
Spring-tx-xxx.jar
当然还有jdbc驱动包
主要的类就是TransactionTemplate和JdbcTemplate
@Test public void testDemo(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///user"); dataSource.setUsername("root"); dataSource.setPassword("root"); //定义事务的管理者 DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); //创建事务的模板 TransactionTemplate transactionTemplate = new TransactionTemplate(); //设置事务的管理者是谁。一定要设置管理者,否则无法使用事务。 transactionTemplate.setTransactionManager(transactionManager); final JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); //设置回调,也就是在里面写我们真正要操作的 crud逻辑 transactionTemplate.execute(new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus arg0) { try { //在这里面写 crud代码。 这个doInTransaction 方法会被spring的框架所调用。 //它在底下开启完事务之后,就用这个方法。 String sql = "insert into t_user values (null , ? , ?)"; jdbcTemplate.update(sql , "aobama2","6666222"); int a = 10 / 0 ; } catch (DataAccessException e) { e.printStackTrace(); //设置回滚的标记。 arg0.setRollbackOnly(); } return null; } }); }
2. 声明式 - XML
导入jar包Spring-jdbc-XXX.jar
Spring-tx-xxx.jar
当然还有jdbc驱动包
导入约束
aop \ tx \bean 约束
配置事务
可以看出,事务的本质也是进行了aop的增强,在前面加上了事务的开启,后面加上了事务的提交和回滚
<!-- 以下是配置事务 事务的配置,其实就是AOP的操作。 --> <!-- 1. 声明事务的建议 会对哪一个方法进行事务啊。 就是在这里进行配置--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"></property> </bean> <tx:advice id="advice" transaction-manager="transactionManager"> <!-- 这个tx:attributes 就是用来控制到底给哪个方法加入事务 --> <tx:attributes> <!-- * 表示给前面找到的所有方法都应用事务 dao ==== jdbctemplate hibernatetemplate--> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 还少一件事情, 对哪些类的,哪些方法,进行事务。 --> <aop:config> <aop:pointcut expression="execution(* com.itheima.service.*.*(..))" id="pointCut"/> <!-- 给上面的pointCut 切入点,找到的方法,应用上面给出的事务建议。也就是给这些方法,都是用事务来管理 --> <aop:advisor advice-ref="advice" pointcut-ref="pointCut"/> </aop:config>
3. 声明式 - 注解(重要 - 最常用的方式)
在xml里面指定事务使用的管理者是谁<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_for_test"></property> <property name="user" value="root"></property> <property name="password" value="123456"></property> </bean> <!-- 打开注解开关 这里是指定注解的事务,采用什么管理者。 光有那个类上的注解,是不够的,因为spring 也不知道我们打算使用什么类型的管理者来操作事务。 --> <tx:annotation-driven transaction-manager="transactionManager"/> 2. 在业务逻辑类上面打上注解 ,当然如果想指定具体的某一个方法采用事务,也可以在方法上面打上注解 public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override @Transactional public void save() { System.out.println("userDao的save方法执行了"); String sql = "insert into user values(null,?,?)"; jdbcTemplate.update(sql, "测试1","测试1"); int i= 10/0; jdbcTemplate.update(sql, "测试2","测试2"); System.out.println("保存成功"); } }
相关文章推荐
- Spring框架的第三天(AOP注解方式、JDBC模板、事务管理)
- Spring入门(三)— AOP注解、jdbc模板、事务
- 第四天AOP注解的方式以及spring的JDBC模板
- spring框架学习(六)AOP事务及spring管理事务方式之Template模板
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- Spring之AOP声明式事务管理(采用xml的配置方式更好)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring 使用注解方式进行事务管理
- Spring 使用注解方式进行事务管理
- Spring 使用注解方式进行事务管理
- Spring 【Aspectj】进行AOP开发 (【注解】方式)
- Spring AOP如何整合redis(注解方式)实现缓存统一管理详解
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- spring AOP自定义注解方式实现日志管理的实例讲解
- Spring 基于注解方式进行事务管理
- Spring 使用注解方式进行事务管理配置方式
- Spring 使用Spring注解方式管理事务与传播行为