Day49-Spring-03

来源:互联网 发布:淘宝信鸽出售 编辑:程序博客网 时间:2024/06/07 02:16

一、AOP注解(注解方式)

 在Spring02中讲述了xml方式的aop,现在讲解aop的注解形式。
  1. 导入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包一样)

  2. 导入约束
    导入AOP的约束

  3. 在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>
  1. 在增强类中打上注解。
        @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模板 入门 – 以向数据库插入数据为例子

  1. 导入jar包
    额外导入 三个jar包
    spring-jdbc-xxx.jar
    spring-tx-xxx.jar (事务的包)
    jdbc的驱动包

  2. 写代码
    如何写这段代码:
    只需要记住一个关键的类名: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

  1. 导入jar包
    Spring-jdbc-XXX.jar
    Spring-tx-xxx.jar
    当然还有jdbc驱动包
  2. 导入约束
    aop \ tx \bean 约束

  3. 配置事务
    可以看出,事务的本质也是进行了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. 声明式 - 注解(重要 - 最常用的方式)

  1. 在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("保存成功");      }}
原创粉丝点击