Spring JDBC 基础学习

Spring JDBC 简介
Spring JDBC配置步骤
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    </dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 数据源配置 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/springtest?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </bean>
    <!-- JdbcTemplate提供数据CRUD的API -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="employeeDao" class="com.springtest.spring.jdbc.dao.EmployeeDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

</beans>
public class Employee {
    private Integer eno;
    private String ename;
    private Float salary;
    private String dname;
    private Date hiredate;

    public Integer getEno() {
        return eno;
    }

    public void setEno(Integer eno) {
        this.eno = eno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Float getSalary() {
        return salary;
    }

    public void setSalary(Float salary) {
        this.salary = salary;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eno=" + eno +
                ", ename='" + ename + '\'' +
                ", salary=" + salary +
                ", dname='" + dname + '\'' +
                ", hiredate=" + hiredate +
                '}';
    }
}
public class EmployeeDao {
    private JdbcTemplate jdbcTemplate;

    public Employee findById(Integer eno){
        String sql = "select * from employee where eno = ?";
        Employee employee = jdbcTemplate.queryForObject(sql, new Object[]{eno}, new BeanPropertyRowMapper<Employee>(Employee.class));
        return employee;
    }
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        EmployeeDao employeeDao = context.getBean("employeeDao", EmployeeDao.class);
        Employee employee = employeeDao.findById(3308);
        System.out.println(employee);
    }
}
日志打印

在依赖文件中添加日志依赖,自动打印日志。

<!--logback日志组件,spring挺架默认集成-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<dependency>

编程式事务

事务:事务是以一种可靠的、一致的方式,访问和操作数据库的程序单元
说人话: 要么把事情做完,要么什么都不做,不要做一半
事务依赖于数据库实现MySQL通过事务区作为数据缓冲地带
编程式事务:编程式事务是指通过代码手动提交回滚事务的事务控制方法
SpringJDBC通过TransactionManager事务管理器实现事务控制
事务管理器提供commit/rollback方法进行事务提交与回滚

  1. 在配置文件applicationContext.xml中添加bean.
<!--事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
  1. 在EmployeeService类中注入事务bean,并生成get和set方法。
private DataSourceTransactionManager transactionManager;

public DataSourceTransactionManager getTransactionManager() {
        return this.transactionManager;
    }

    public void setTransactionManager(DataSourceTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
  1. 在配置文件applicationContext.xml的 EmployeeService bean 中继续完成事务bean的注入。
<bean id="employeeService" class="com.imooc.spring.jdbc.service.EmployeeService">
        <property name="employeeDao" ref="employeeDao"/>
       	<!--注入事务bean-->
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
  1. 在更新数据的方法中使用事务。
public void batchImport() {
		 // 定义事物的默认标准配置
        TransactionDefinition definition = new DefaultTransactionDefinition();
       	// 开始事务,并返回事务状态,事务状态为当前事物的执行阶段。
        TransactionStatus status = this.transactionManager.getTransaction(definition);

        try {
            for(int i = 1; i <= 10; ++i) {
                Employee employee = new Employee();
                employee.setEno(8000 + i);
                employee.setEname("员工" + i);
                employee.setSalary(4000.0F);
                employee.setDname("市场部");
                employee.setHiredate(new Date());
                this.employeeDao.insert(employee);
            }
            // 提交事务
            this.transactionManager.commit(status);
        } catch (RuntimeException var5) {
            this.transactionManager.rollback(status);
            throw var5;
        }
    }

声明式事务

声明式事务指在不修改源码情况下通过配置形式自动实现事务控制,声明式事务本质就是AOP环绕通知
当目标方法执行成功时,自动提交事务
当目标方法抛出运行时异常时,自动事务回滚

  1. 引入实现AOP环绕通知的依赖。
<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
  1. 在配置文件applicationContext.xml配置声明式事务。
<!-- 在配置文件中增加新的命名空间和文件地址 -->
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
<!-- 1.事务管理器,用于创建事务/提交/回滚 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--2.事务通知配置,决定哪些方法使用事务,哪些方法不使用事务 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 目标方法名为batchImport时,启用声明式事务,成功提交,运行时异常回滚 -->
            <tx:method name="batchImport" propagation="REQUIRED"/>
            <tx:method name="batch*" propagation="REQUIRED"/>
            <!-- 设置所有findXXX方法不需要使用事务 -->
            <tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
            <tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>

            <tx:method name="importJob1" propagation="REQUIRES_NEW"/>
            <tx:method name="importJob2" propagation="REQUIRES_NEW"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--定义声明式事务的作用范围-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.imooc..*Service.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>

事务传播行为

事务传播行为是指多个拥有事务的方法在嵌套调用时的事务控制方式
XML:<tx:method name="…"propagation=“REQUIRED”/>
注解:@Transactional(propagation=Propagation.REQUIRED
PROPAGATION REQUIRED(默认):如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择
PROPAGATION SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
PROPAGATION REQUIRES NEW:新建事务,如果当前存在事务,把当前事务挂起
PROPAGATION NOT SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION NESTED:如果当前没有事务,则执行与如果当前存在事务,则在嵌套事务内执行PROPAGATION REOUIRED类似的操作

注解式声明式事务

编写applicationContext.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.imooc"/>
    <!--数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/imooc?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 启用注解形式声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

在类或方法上直接添加Transactioanal注解即可。

@Transactional(
    propagation = Propagation.NOT_SUPPORTED,
    readOnly = true
)

@Transactional
06-05 20:01