SpringJDBC和事物控制

1.Spring整合JDBC环境

 

spring框架除了提供IOC与AOP核心功能外,同样提供了基于JDBC的数据访问功能,使得访问持久层数据更加方便。使用SpringJDBC环境,首先需要一套Spring整合JDBC的环境

1.2添加依赖坐标

 <!--导入相关依赖坐标    -->
    <!--spring环境依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.18</version>
    </dependency>

    <!--spring测试环境    -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.3.18</version>
      <scope>test</scope>
    </dependency>

    <!--spring AOP  -->
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.6</version>
      <scope>runtime</scope>
    </dependency>

    <!--spring_jdbc  -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <!--    spring 事物-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.3.23</version>
    </dependency>

    <!--  mysql-->
    <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
    <dependency>
      <groupId>com.mysql</groupId>
      <artifactId>mysql-connector-j</artifactId>
      <version>8.0.31</version>
    </dependency>

    <!--c3p0连接池-->
    <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.5</version>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>RELEASE</version>
      <scope>compile</scope>
    </dependency>

1.3添加jdbc配置文件

在src/main/resources目录下新建jdbc.properties配置文件,并设置对应配置信息

#驱动名
jdbc.driver =com.mysql.cj.jdbc.Driver
#数据库连接
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_jdbc?serverTimezone=UTC&useSSL=false&charaterEncodeing=UTF-8
#数据库用户名称
jdbc.user=root(写自己数据库名称,一般为root)
#数据库用户密码
jdbc.password=111111(自己数据库密码)

1.4修改spring配置文件

<?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.xsd">


    <!--开启自动化扫描-->
    <context:component-scan base-package="com.xxxx"/>
<!--    加载properties配置文件,可以读取jdbc。properties配置文件中的数据-->
    <context:property-placeholder location="jdbc.properties"/>


</beans>

1.5配置数据源

由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

C3p0是一个开源的JDBC连接池,它实现了数据源,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernet,Spring等。c3p0有自动回收空闲连接功能。

C3p0数据源配置

<!--    配置c3p0数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--        通过properties标签配置对应的值,value属性值对应的是properties配置文件中的值-->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>

    </bean>
  

1.6模板类配置

  <!--        配置jdbcTemplate模板对象,并注入一个数据源-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <property name="dataSource" ref="dataSource"/>
    </bean>

1.7JDBC测试

1.7.1创建指定数据库

1.7.2使用Junit测试

通过junit测试jdbcTemplate bean是否获取到

package com.xxxx.test;

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

public class SpringJdbcTest01 {
    @Test
    public void  testJdbc(){
        //获取Spring的上下文环境
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
        //得到模板类 JdbcTemplate 对象
        JdbcTemplate jdbcTemplate= (JdbcTemplate) ac.getBean("jdbcTemplate");
        //crud操作
        //定义sql语句
        String sql="select count(1) from tb_account";
        //执行查询操作
        Integer total=jdbcTemplate.queryForObject(sql,Integer.class);
        System.out.println("总记录数:"+total);
    }

}

1.7.3环境测试优化

当有多个测试类时,可设置一个父类Basetest,当使用测试类的时候只需要继承父类的方法

package com.xxxx.test;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class) //将测试运行在Spring测试环境中
@ContextConfiguration (locations ={"classpath:spring.xml"}) //设置要加载的配置文件
public class BaseTest {

}

2.持久层账户模块操作

当完成Spring jdbc 环境集成后,这里使用spring jdbc完成账户表单crud(增删改查)操作

2.1账户接口方法定义

2.1.1 定义实体类

Account,java

package com.xxxx.po;

import java.util.Date;

/**
 * 用户账户类
 */
public class Account {
    private  Integer account; //账户ID,主键
    private  String accountName; //账户名称
    private  String accountType; //庄户类型
    private  Double money;//账户金额
    private  String remark; //账户备注
    private  Date  createTime; //创建时间
    private  Date updateTime; //修改时间
    private  Integer userId; //用户ID,账户所属用户

    public Account() {
    }

    public Account(String accountName, String accountType, Double money, String remark, Integer userId) {
        this.accountName = accountName;
        this.accountType = accountType;
        this.money = money;
        this.remark = remark;
        this.userId = userId;
    }

    @Override
    public String toString() {
        return "Account{" +
                "account=" + account +
                ", accountName='" + accountName + '\'' +
                ", accountType='" + accountType + '\'' +
                ", money=" + money +
                ", remark='" + remark + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", userId=" + userId +
                '}';
    }

    public Integer getAccount() {
        return account;
    }

    public void setAccount(Integer account) {
        this.account = account;
    }

    public String getAccountName() {
        return accountName;
    }

    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }

    public String getAccountType() {
        return accountType;
    }

    public void setAccountType(String accountType) {
        this.accountType = accountType;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}

2.1.2定义接口类

IAccountDao.java

package com.xxxx.dao;

import com.xxxx.po.Account;

import java.util.List;

/**
 * 账户模块 定义接口
 *  1.添加账户
 *       添加账户记录,返回受影响的行数
 *       添加账户记录,返回主键
 *       批量添加账户记录,返回受影响的行数
 *  2.修改账户
 *       修改账户记录,返回受影响的行数
 *       批量修改账户记录,返回受影响的行数
 *  3.删除账户
 *       删除账户记录,返回受影响的行数
 *       批量删除账户记录,返回受影响的行数
 *  4.查询账户
 *       查询指定用户的账户总记录数,返回总记录数
 *       查询指定账户的账户详情,返回账户对象
 *       多条件查询指定用户的账户账户列表,返回账户集合
 *
 */
public interface IAccountDao {

    /**
     * 添加账户
     *      添加账户记录,返回受影响的行数
     * @param account
     * @return
     */
    public int addAccount(Account account);

    /**
     * 添加账户
     *      添加账户记录,返回主键
     * @param account
     * @return
     */
    public int addAccountHasKey(Account account);

    /**
     *添加账户
     *      批量添加账户记录,返回受影响的行数
     * @param accounts
     * @return
     */
    public  int addAccountBatch(List<Account>accounts);

    /**
     * 查询账户
     *       查询指定用户的账户总记录数,返回总记录数
     * @param userId
     * @return
     */
    public int queryAccountCount(int userId);

    /**
     * 查询账户
     *      查询指定账户的账户详情,返回账户对象
     * @param accountID
     * @return
     */
    public Account queryAccountByID(int accountID);

    /**
     * 查询账户
     *      多条件查询指定用户的账户账户列表,返回账户集合
     * @param userId 指定用户的ID
     * @param accountName 账户名称(模糊查询)
     * @param accountType 账户类型
     * @param createTime 创建时间(大于当前时间)
     * @return
     */
    public List<Account> queryAccountByParams(Integer userId,String accountName,String accountType,String createTime);

    /**
     * 修改账户
     *      修改账户记录,返回受影响的行数
     * @param account
     * @return
     */
    public int updateAccount(Account account);

    /**
     * 修改账户
     *      批量修改账户记录,返回受影响的行数
     * @param accounts
     * @return
     */
    public  int updateAccountBath(List<Account> accounts);

    /**
     * 删除账户
     *      删除账户记录,返回受影响的行数
     * @param accountID
     * @return
     */
    public int deleteAccount(int accountID);

    /**
     * 删除账户
     *     批量删除账户记录,返回受影响的行数
     * @param ids
     * @return
     */
    public int deleteAccountBath(Integer[]ids);


}

2.2账户记录添加实现

这里对于账户记录添加方式分为三种方式:添加单条记录返回受影响行数、添加单条记录返回主键、批量添加多条记录

2.2.1添加账户记录

 /**
     * 添加账户记录,返回受影响的行数
     * @param account
     * @return
     */
    @Override
    public int addAccount(Account account) {
        //定义sql语句
        String sql ="insert into tb_account(account_name,account_type,money,remark, create_time,update_time,user_id) " +
                "values(?,?,?,?,now(),now(),?)";
        //设置参数
        Object[] objs={account.getAccountName(),account.getAccountType(),account.getMoney(),
                account.getRemark(),account.getUserId()};

        int row =jdbcTemplate.update(sql,objs);
        return row;
    }

测试方法

 @Test
    public  void testAddAccount(){
        //准备要添加的数据
        Account account=new Account("账户3","工商银行",200.0,"奖金",1);
        //调用对象中的添加方法,返回受影响的行数
        int row =accountDao.addAccount(account);

        System.out.println("添加账户,受影响的行数:"+row);
    }

2.2.2添加记录返回主键

 /**
     * 添加账户记录,返回主键
     * @param account
     * @return
     */
    @Override
    public int addAccountHasKey(Account account) {
        //定义sql语句
        String sql="insert into tb_account(account_name,account_type,money,remark, create_time,update_time,user_id) " +
                "values(?,?,?,?,now(),now(),?)";
        //定义KeyHolder对象 获取记录的主键值
        KeyHolder keyHolder=new GeneratedKeyHolder();
        jdbcTemplate.update(connection->{
            //预编译sql,并设置返回主键
            PreparedStatement ps=connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            //设置参数
            ps.setString(1,account.getAccountName());
            ps.setString(2,account.getAccountType());
            ps.setDouble(3,account.getMoney());
            ps.setString(4,account.getRemark());
            ps.setInt(5,account.getUserId());
            //返回预编译对象
            return ps;
        },keyHolder);
        //得到返回的主键
        int key=keyHolder.getKey().intValue();
        return key;
    }

测试方法

     /**
     * 添加账户记录,返回主键
     */
    @Test
    public void testAddAccountHasKey(){
        //准备要添加的数据
        Account account=new Account("账户4","中国银行",300.0,"绩效奖",2);
        //调用对象中的添加方法,返回主键
        int key =accountDao.addAccountHasKey(account);
        System.out.println("添加账户,返回主键:"+key);
    }

2.2.3批量添加账户记录

/**
     * 批量添加账户记录,返回受影响的行数
     * @param accounts
     * @return
     */
    @Override
    public int addAccountBatch(List<Account> accounts) {
        //定义sql语句
        String sql="insert into tb_account(account_name,account_type,money,remark, create_time,update_time,user_id) " +
                "values(?,?,?,?,now(),now(),?)";

         int rows=jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Account account=accounts.get(i);
                //设置参数
                ps.setString(1,account.getAccountName());
                ps.setString(2,account.getAccountType());
                ps.setDouble(3,account.getMoney());
                ps.setString(4,account.getRemark());
                ps.setInt(5,account.getUserId());

            }

            @Override
            public int getBatchSize() {
                return accounts.size();
            }
        }).length;
        return rows;
    }

测试方法

/**
     * 批量添加账户记录,返回受影响行数
     */
    @Test
    public void testBatchAddAccount(){
        //准备要添加的数据
        Account account=new Account("账户5","农商银行",300.0,"奖金",3);
        Account account2=new Account("账户6","建设银行",500.0,"绩效奖",3);
        Account account3=new Account("账户7","中国银行",650.0,"全勤奖",3);

        List<Account> accounts=new ArrayList<>();
        accounts.add(account);
        accounts.add(account2);
        accounts.add(account3);
        int rows=accountDao.addAccountBatch(accounts);
        System.out.println("批量添加账户,受影响的行数:"+rows);
    }

2.3账户记录查询实现

账户记录查询这里提供了三种查询方式,查询指定用户所有账户记录数、查询单条账户记录详情

多条件查询指定用户记录。

2.3.1查询用户的账户总记录数

 /**
     * 查询指定用户的账户总记录数,返回总数量
     * @param userId
     * @return
     */
    @Override
    public int queryAccountCount(int userId) {
        //定义sql语句
        String sql="select count(1) from tb_account where user_id =?";
        //查询方法
        int count=jdbcTemplate.queryForObject(sql,Integer.class,userId);

        return count;
    }

测试方法

     /**
     * 查询指定用户的账户总记录数,返回总数量
     */
    @Test
    public  void testQueryAccountTest(){
        int  total=accountDao.queryAccountCount(1);
        System.out.println("查询指定用户的账户总记录数,返回总数量"+total);
    }

2.3.2查询指定账户记录的详情

/**
     * 查询指定账户记录的详情,返回账户对象
     * @param accountId
     * @return
     */
    @Override
    public Account queryAccountByID(int accountId) {
        //定义sql语句
        String sql="select * from tb_account where account_id=?";
        //查询对象
        Account account= jdbcTemplate.queryForObject(sql, (ResultSet rs, int i)-> {
            Account acc=new Account();
            acc.setAccount(accountId);
            acc.setAccountName(rs.getString("account_name"));
            acc.setAccountType(rs.getString("account_type"));
            acc.setMoney(rs.getDouble("money"));
            acc.setRemark(rs.getString("remark"));
            acc.setUserId(rs.getInt("user_id"));
            acc.setCreateTime(rs.getDate("create_time"));
            acc.setUpdateTime(rs.getDate("update_time"));
            return acc;
        },accountId);
        return account;
    }

测试方法

     /**
     * 查询指定用户的账户总记录数,返回账户详情
     */
    @Test
    public  void testQueryAccountById(){
        Account account=accountDao.queryAccountByID(1);
        System.out.println("账户详情:"+account.toString());
    }

2.3.3多条件查询指定用户的账户记录列表

    /**
     * 多条件查询指定用户的账户记录列表,返回账户集合
     * @param userId 指定用户的ID
     * @param accountName 账户名称(模糊查询)
     * @param accountType 账户类型
     * @param createTime 创建时间(大于当前时间)
     * @return
     */
    @Override
    public List<Account> queryAccountByParams(Integer userId, String accountName, String accountType, String createTime) {
       //定义sql语句
        String sql="select * from tb_account where user_id = ?";
        //定义参数列表
        List<Object> params=new ArrayList<>();
        params.add(userId);
        //判断参数是否为空,如果不为空,拼接sql语句语句及设置对应的参数
        //账户名称
        if(StringUtils.isNoneBlank(accountName)){
            //拼接sql语句
            sql+=" and account_name like  concat('%', ? ,'%')";
            //设置参数
            params.add(accountName);
        }
        //账户类型
        if(StringUtils.isNoneBlank(accountType)){
            //拼接sql语句
            sql+=" and account_type = ?";
            //设置参数
            params.add(accountType);
        }
        //创建时间
        if(StringUtils.isNoneBlank(createTime)){
            //拼接sql语句
            sql+=" and account_time < ?";
            //设置参数
            params.add(createTime);
        }
        //将集合转换为数组
        Object[] objs=params.toArray();
        //查询集合
        List<Account>accountList =jdbcTemplate.query(sql,objs,(ResultSet rs, int i)-> {
            Account acc=new Account();
            acc.setAccount(rs.getInt("account_id"));
            acc.setAccountName(rs.getString("account_name"));
            acc.setAccountType(rs.getString("account_type"));
            acc.setMoney(rs.getDouble("money"));
            acc.setRemark(rs.getString("remark"));
            acc.setUserId(rs.getInt("user_id"));
            acc.setCreateTime(rs.getTimestamp("create_time"));
            acc.setUpdateTime(rs.getTimestamp("update_time"));
            return acc;
        });
        return accountList;
    }

测试方法

@Test
    /**
     * 多条件查询指定用户的账户记录列表,返回账户集合
     */
    public void testQueryAccountList(){
        List<Account>accountList=accountDao.queryAccountByParams(3,null,null,null);
       // System.out.println(accountList.toString());
        List<Account>accountList2=accountDao.queryAccountByParams(3,"6","建设银行",null);
        System.out.println(accountList2.toString());
    }

2.4.账户记录更新实现

2.4.1更新账户记录

/**
     * 更新账户,返回受影响的行数
     * @param account
     * @return
     */
    @Override
    public int updateAccount(Account account) {
        //定义sql
        String sql="update tb_account set account_name = ? ,account_type = ? ,money = ? ,remark =? ," +
                "update_time =now() ,user_id = ? where account_id = ?";
        //设置参数
        Object[] objs ={
                account.getAccountName(),account.getAccountType(),account.getMoney(),
                account.getRemark(),account.getUserId(),account.getAccount()};
        int row =jdbcTemplate.update(sql,objs);
        return row;
    }

测试方法

 /**
     * 修改账户记录,返回受影响的行数
     */
    @Test
    public void  testUpdateAccount(){
        //准备要添加的数据
        Account account=new Account("账户11","农业银行",2000.0,"奖金奖",1);
        account.setAccount(1);
        int row =accountDao.updateAccount(account);
        System.out.println("修改账户记录,返回受影响的行数:"+row);

    }

2.4.2批量修改账户记录

/**
     * 批量修改账户记录,返回受影响行数
      * @param accounts
     * @return
     */
    @Override
    public int updateAccountBath(List<Account> accounts) {
        //定义sql
        String sql="update tb_account set account_name = ? ,account_type = ? ,money = ? ,remark =? ," +
                "update_time =now() ,user_id = ? where account_id = ?";
        int rows= jdbcTemplate.batchUpdate(sql,new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Account account=accounts.get(i);
                //设置参数
                ps.setString(1,account.getAccountName());
                ps.setString(2,account.getAccountType());
                ps.setDouble(3,account.getMoney());
                ps.setString(4,account.getRemark());
                ps.setInt(5,account.getUserId());
                ps.setInt(6,account.getAccount());
            }

            @Override
            public int getBatchSize() {
                return accounts.size();
            }
        }).length;
        return rows;
    }

测试方法

/**
     * 批量修改账户记录,返回受影响行数
     */
    @Test
    public void testBathUpdateAccount(){
        //准备要添加的数据
        Account account=new Account("账户55","农商银行",3300.0,"奖金",3);
        account.setAccount(5);
        Account account2=new Account("账户66","建设银行",5600.0,"绩效奖",3);
        account2.setAccount(6);
        Account account3=new Account("账户77","中国银行",6050.0,"全勤奖",3);
        account3.setAccount(7);

        List<Account> accounts=new ArrayList<>();
        accounts.add(account);
        accounts.add(account2);
        accounts.add(account3);
        int rows=accountDao.addAccountBatch(accounts);
        System.out.println("批量修改账户记录,返回受影响行数:"+rows);
    }

2.5账户记录删除实现

2.5.1删除账户记录

/**
     * 删除账户记录,返回受影响的行数
     * @param accountID
     * @return
     */
    @Override
    public int deleteAccount(int accountID) {
        //定义sql语句
        String sql="delete from  tb_account  where account_id = ?";
        int row=jdbcTemplate.update(sql,accountID);
        return row;
    }

测试方法

 /**
     * 删除账户记录,返回受影响的行数
     */
    @Test
    public void testDeleteAccount(){
        int row=accountDao.deleteAccount(1);
        System.out.println("删除账户记录,返回受影响的行数:"+row);
    }

2.5.2批量删除账户记录

/**
     * 批量删除账户记录,返回受影响的行数
     * @param ids
     * @return
     */
    @Override
    public int deleteAccountBath(Integer[] ids) {
        //定义sql语句
        String sql="delete from  tb_account  where account_id = ?";
        int rows =jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                ps.setInt(1,ids[i]);
            }

            @Override
            public int getBatchSize() {
                return ids.length;
            }
        }).length;


        return rows;
    }

测试方法

/**
     * 批量删除账户记录,返回受影响的行数
     */
    @Test
    public void testBatchAccount(){
       Integer[] ids={2,3,4};
       int rows=accountDao.deleteAccountBath(ids);
        System.out.println("批量删除账户记录,返回受影响的行数:"+rows);

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值