前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring-Jdbc/Transaction

Spring-Jdbc/Transaction

作者头像
Java开发者之家
发布2021-06-17 16:49:42
2250
发布2021-06-17 16:49:42
举报
文章被收录于专栏:Java开发者之家Java开发者之家

# Spring-JDBC与Spring 事务

# 使用c3p0链接池配置信息
代码语言:javascript
复制
jdbc.user=root
jdbc.password=xxxxxx
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/Xxxx?useSSL=false&serverTimezone=UTC

jdbc.initPoolSize=5
jdbc.maxPoolSize=20
# spring配置文件
代码语言:javascript
复制
<?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"
       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-4.0.xsd">

    <!--导入资源配置文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>

        <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>

    </bean>

    <!--配置spring的JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

</beans>
# spring-jdbc测试
代码语言:javascript
复制
package top.finen.spring.jdbc;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JDBCTest {
    private ApplicationContext ctx = null;
    private JdbcTemplate jdbcTemplate;

    {
        ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
    }

    /**
     * 批量更新
     * 最后一个参数是Object[]的List类型:因为修改一条记录需要一个Object的数组,那么多条就需要多个Object数组
     */
    @Test
    public void testBatchUpdate() {
        String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(?, ?, ?)";
        List<Object[]> batchArgs = new ArrayList<>();
        batchArgs.add(new Object[]{"AA", "88888@qq.com", 1});
        batchArgs.add(new Object[]{"BB", "88888@qq.com", 1});
        batchArgs.add(new Object[]{"CC", "88888@qq.com", 3});
        batchArgs.add(new Object[]{"VF", "88888@qq.com", 1});
        batchArgs.add(new Object[]{"FFF", "88888@qq.com", 1});
        batchArgs.add(new Object[]{"AGGA", "88888@qq.com", 1});
        batchArgs.add(new Object[]{"WW", "88888@qq.com", 1});
        jdbcTemplate.batchUpdate(sql, batchArgs);
    }

    @Test
    public void testUpdate() {
        String sql = "UPDATE employees SET last_name = ? WHERE id = ?";
        jdbcTemplate.update(sql, "Tom", 3);
    }


    @Test
    public void testDataSource() throws SQLException {
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource.getConnection());
    }


    /**
     * 从数据库中获取一条记录,实际得到对应的一个对象
     * 注意:不是调用queryForObject(String sql, Class<Employee> requireType, Object... args)方法,
     * 而需要调用queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
     * 1. 其中的RowMapper指定如何如映射结果集的行,常用的实现类为BeanPropertyRowMapper
     * 2.使用SQL中的列的别名完成列名和类的属性名的映射,例如:last_name lastName
     * 3.不支持级联属性,JdbcTemplate到底是一个Jdbc的小工具,而不是ORM框架
     */
    @Test
    public void testQueryForObject() {

        String sql = "SELECT id, last_name lastName, email FROM employees WHERE id = ?";
        RowMapper<Employee> employeeRowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
        Employee employee = jdbcTemplate.queryForObject(sql, employeeRowMapper, 1);
        System.out.println(employee);

    }

    /**
     * 查到实体类的集合
     * 注意调用不是的queryForList
     */
    @Test
    public void testQueryForList() {
        String sql = "SELECT id, last_name lastName, email FROM employees WHERE id > ?";
        RowMapper<Employee> employeeRowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
        List<Employee> employees = jdbcTemplate.query(sql, employeeRowMapper, 3);
        System.out.println(employees);
    }

    /**
     * 获取单列的值或者做统计查询
     *
     */
    @Test
    public void testQueryForObject2() {

        String sql = "SELECT count(id) FROM employees";
        long count = jdbcTemplate.queryForObject(sql, Long.class);

        System.out.println(count);

    }


}
# Spring使用具名参数
代码语言:javascript
复制
<!--配置namedParameterJdbcTemplate,该对象可以使用具名参数,其没有无参数的构造器指定参数-->
<bean id="namedParameterJdbcTemplate"
      class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <constructor-arg ref="dataSource"></constructor-arg>
</bean>
代码语言:javascript
复制
@Test
public void testNamedParameterJdbcTemplate() {
    String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(:ln, :email, :deptid)";
    Map<String, Object> paraMap = new HashMap<>();
    paraMap.put("ln", "FF");
    paraMap.put("email", "sss@888.com");
    paraMap.put("deptid", 2);
    namedParameterJdbcTemplate.update(sql, paraMap);
}

/**
 * 使用具名参数时,可以update(String sql, SqlParameterSource paramSource)方法进行更新操作
 * 1.SQL语句的参数与类的属性一致
 * 2.使用SqlParameterSource的BeanPropertySqlParameterSource实现类作为参数
 */
@Test
public void testNamedParameterJdbcTemplate2() {
    String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(:lastName, :email, :deptId)";
    Employee employee = new Employee();
    employee.setLastName("sssss");
    employee.setEmail("@@@ssss.com");
    employee.setDeptId(1);
    SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(employee);
    namedParameterJdbcTemplate.update(sql, sqlParameterSource);
}

@Test
public void testEmployeeDao() {
    System.out.println(employeeDao.get(1));
}
# Spring的事物管理
代码语言:javascript
复制
<!--配置事物管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--启用事物注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
代码语言:javascript
复制
@Transactional
@Override
public void purchase(String username, String isbn) {
    //1.获取书的单价
    int price = bookShopDao.findBookPriceByIsbn(isbn);

    //2.更新书的库存
    bookShopDao.updateBookStock(isbn);

    //3.更新用户余额
    bookShopDao.updateUserAccount(username, price);
}
# Spring 事物传播属性、事物隔离级别、回滚

当事务方法被另一个事务方法调用时,必须制定事务应该如何传播。

事务的传播行为可以有传播属性指定,Spring订了7种类型的传播行为。

REQUIRED 如果有事务在运行,当前的方法就在这个内运行,否则,就启动另一个事务,并在自己的事务内运行。

REQUIRED_NEW 当前的方法必须启动新事务,并在他自己的事务内运行,如果有事务在运行,应该将它挂起。

SUPPORTS 如果有事务在运行,当前的方法就在这个事物内运行,否则它可以不运行在事务中。

NOT_SUPPORTS 当前的方法不应该运行在事物中,如果有运行的事务,将它挂起。

MANDATORY 当前方法必须运行在事务内部,如果没有正在运行的事务。就跑出异常。

NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事物内运行,否则,就启动一个新的事务。并在他自己的事务内运行。

代码语言:javascript
复制
/**
     * 添加事物注解
     * 使用propagation指定事务的传播行为,即当前事务方法被另一个事物调用时,如何使用事务
     * 默认取值为REQUIRED,即使用调用方法的事务
     * 使用isolation指定事物的隔离级别,最常用取值为READ_COMMITTED
     * 默认情况下Spring的声明式事物对所有的运行异常进行回滚。也可以通过对应的属性进行设置。通常情况下去默认值即可。
     * 使用readOnly指定是否只读,表示这个事物只读取数据但不更新数据,这样可以帮助数据库引擎优化事物,若真的是一个只读取数据的方法,应设置readOnly为true
     * 使用timeout指定强制回滚之前事务可以占用的时间
     * @param username
     * @param isbns
     */
    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.READ_COMMITTED,
            timeout = 1000,
            readOnly = false,
            noRollbackFor = {UserAccountException.class})
    @Override
    public void checkout(String username, List<String> isbns) {
        for (String isbn: isbns) {
            bookShopService.purchase(username, isbn);
        }
    }
# 基于xml的配置
代码语言:javascript
复制
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
 <context:component-scan base-package="top.finen.spring"></context:component-scan>

 <!-- 配置 C3P0 数据源 -->
 <bean id="dataSource1"
       class="com.mchange.v2.c3p0.ComboPooledDataSource">
     <property name="user" value="${jdbc.user}"></property>
     <property name="password" value="${jdbc.password}"></property>
     <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
     <property name="driverClass" value="${jdbc.driverClass}"></property>

     <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
     <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
 </bean>

 <!-- 配置 Spirng 的 JdbcTemplate -->
 <bean id="jdbcTemplate1"
       class="org.springframework.jdbc.core.JdbcTemplate">
     <property name="dataSource" ref="dataSource1"></property>
 </bean>

 <!-- 配置 bean -->
 <bean id="bookShopDao1" class="top.finen.spring.tx.xml.BookShopDaoImpl">
     <property name="jdbcTemplate" ref="jdbcTemplate1"></property>
 </bean>

 <bean id="bookShopService1" class="top.finen.spring.tx.xml.BookShopServiceImpl">
     <property name="bookShopDao" ref="bookShopDao1"></property>
 </bean>

 <bean id="cashier1" class="top.finen.spring.tx.xml.CashierImpl">
     <property name="bookShopService" ref="bookShopService1"></property>
 </bean>

 <!--配置事务管理器-->
 <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource1"></property>
 </bean>

 <!--事务属性-->
 <tx:advice id="txAdvice" transaction-manager="transactionManager2">
     <tx:attributes>
         <tx:method name="*"/>
     </tx:attributes>
 </tx:advice>

 <!--配置事务切入点,以及把事务切入点和事务属性关联-->
<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* top.finen.spring.tx.xml.BookShopService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"></aop:advisor>
</aop:config>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-02-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # Spring-JDBC与Spring 事务
    • # 使用c3p0链接池配置信息
      • # spring配置文件
        • # spring-jdbc测试
          • # Spring使用具名参数
            • # Spring的事物管理
              • # Spring 事物传播属性、事物隔离级别、回滚
                • # 基于xml的配置
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档