一、日志系统

1. 添加依赖

  1. <dependency>
  2. <groupId>org.slf4j</groupId>
  3. <artifactId>slf4j-api</artifactId>
  4. <version>1.7.7</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>ch.qos.logback</groupId>
  8. <artifactId>logback-classic</artifactId>
  9. <version>1.2.3</version>
  10. </dependency>

我们主动打印日志
把我们查询到的Admin对象以日志的方式进行打印

 Admin admin = adminMapper.selectByPrimaryKey(1);
 // 传入当前类的class属性
 Logger logger = LoggerFactory.getLogger(SpringTest.class);  
 logger.debug(admin.toString());

使用日志打印信息和使用System.out.println() 的方式区别:sysout如果不删除,那么执行到这里必然会打印;如果使用日志方式打印,可以通过日志级别控制信息是否删除

2. logback配置文件

ogback 工作时的具体细节可以通过logback.xml来配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体
            内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger]
                [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="INFO">
        <!-- 指定打印日志的 appender,这里通过“STDOUT”引用了前面配置的 appender -->
        <appender-ref ref="STDOUT" />
    </root>
    <!-- 根据特殊需求指定局部日志级别 -->
    <logger name="com.yixuexi.crowd.mapper" level="DEBUG"/>
</configuration>

二、声明式事务

目标:在框架环境下通过一系列的配置由Spring来管理通用事务操作,然后让我们写的代码能够享受框架提供的服务。

框架的声明式事务底层还是编程式事务来做的
编程式事务:

try{
    //开启事务(关闭自动提交)
    connection.setAutoCommit(false);
    //核心操作
    adminMapper.insert(admin);
    //提交事务
    connection.commit();
}catch (Exception e){
    //回滚事务
    connection.rollback();
}finally {
    //释放连接
    if (connection != null){
        connection.close();
    }
}

1. 实现声明式事务代码

【为了代码规范,这里又创建了一个spring配置文件,spring-persist-tx.xml 单一职责 】

<?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" xmlns:tx="http://www.springframework.org/schema/tx"
       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 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--有关事务的配置文件-->
    <!--配置自动扫描的包,主要是为了吧Service层扫描到IOC容器中-->
    <!--service层中还分了两层,一层是 api包存放接口,impl包存放实现类-->
    <context:component-scan base-package="com.yixuexi.crowd.service"/>

    <!-- 配置事务管理器 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 装配数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置AOP-->
    <aop:config>
        <aop:pointcut id="txPointcut" expression="execution(* *..*ServiceImpl.*(..))"/>
        <!--将切入点表达式和事务通知关联起来-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

    <!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
        <!--配置事务的属性-->
        <tx:attributes>
            <!--查询的方法:配置只读属性,让数据库知道这是一个查询的操作,能够进行一定的优化-->
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="count*" read-only="true"/>
            <tx:method name="query*" read-only="true"/>
            <!--增删改方法:配置事务的传播行为,回滚异常-->
            <!--
            propagation属性: 传播行为
                REQUIRED:默认值,表示当前方法必须工作在事务中,如果当前线程上没有已经开启的事务,则自己开新事务。如果已经有就用有的
                    顾虑:用别人的事务,有可能被回滚
                REQUIRES_NEW:建议使用,不管当前线程上有没有事务都要自己开事务,在自己的事务中运行
                    好处:不会受到其他事务的影响
            -->
            <!--
            rollback-for属性: 配置事务方法针对什么样的异常回滚
                默认:运行时异常归滚,编译时异常不会滚
                建议:编译时异常和运行时异常都回滚
            -->
            <!--注意:必须有下面这个,方法才能有事务  必须配置,如果没有配置,事务对这个方法则不生效-->
            <tx:method name="save*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="batch*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>
</beans>

使用:
创建接口,创建接口实现类(@Service)重写方法,方法的名字满足上面 tx:method 的name即可,那么该方法就被声明时事务了