Java操作数据库

JDBC操作数据库

优化之前版本(浪费性能)

import java.sql.*;
public class JDBCTest {
    public static void main(String[] args) {
        //获取连接
        Connection connection = null;
        //声明
        PreparedStatement statement = null;
        //结果集
        ResultSet resultSet = null;
        try{
            //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名?characterEencoding=UTF-8","root","root");
            //3.设置sql
            String slq = "select * from user where id = ?";
            //4.创建statement
            statement = connection.prepareStatement(slq);
            //5.设置参数
            statement.setInt(1,1);
            //6.执行查询,获取ResultSet
            resultSet = statement.executeQuery();
            //7.解析结果
            while (resultSet.next()){
                System.out.println("用户id:"+resultSet.getInt("id"));
                System.out.println("用户username:"+resultSet.getString("username"));
                System.out.println("用户birthday:"+resultSet.getDate("birthday"));
                System.out.println("用户sex:"+resultSet.getString("sex"));
                System.out.println("用户address:"+resultSet.getString("address"));
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //8.释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

优化版本

  1. 创建工具类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * 自定义JDBC的工具类
 * 编写获取连接代码
 * 提供方法,返回数据库连接对象
 *
 * 资源浪费:
 *  驱动注册不需要每次都执行,执行一次即可,定义在static代码块
 *  数据库连接信息,url,用户名,密码使用一次即可
 */
public class JDBCUtil {

    private static String url = "jdbc:mysql://localhost:3306/数据库名";
    private static String driverClass = "com.mysql.jdbc.Driver";
    private static String user = "root";
    private static String password = "root";

    static {
        try {
            //注册驱动
            Class.forName(driverClass);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 静态方法,获取连接
     * @return
     */
    public static Connection getConnection() throws Exception{
        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }

    /**
     * 静态方法,关闭连接
     * @param connection
     * @param statement
     * @param set
     */
    public static void closeSources(Connection connection, Statement statement, ResultSet set){
        if(set!=null)
            try {
                set.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        if(statement!=null)
            try {
                statement.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        if(connection!=null)
            try {
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}
  1. 使用工具类
import java.sql.*;

/**
 * 工具类测试查询
 * 处理异常
 */
public class Demo2 {

    public static void main(String[] args) {
        Connection con = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //工具了,获取数据库连接
            con = JDBCUtil.getConnection();
            //获取数据库SQL执行对象
            stat = con.createStatement();
            //执行查询,获取结果集
            String sql = "select * from category";
            rs = stat.executeQuery(sql);
            //循环遍历结果集
            while (rs.next()){
                System.out.println(rs.getString("pid")+"\t"+rs.getString("pname")+"\t"+rs.getInt("price"));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放资源,直接调用工具类的方法
            JDBCUtil.closeSources(con,stat,rs);
        }
    }

PreparedStatement

import com.jdbcutils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * 预处理对象
 * 数据库SQL语句执行对象Statemnet接口
 * 子接口:PreparedStatement
 * 预编译:SQL语句存储在对象中,高效执行,
 * 获取Statement接口对象PreparedStatement
 * 高效:反复执行同一个SQL语句
 */
public class PreparedStatementTest2 {

    public static void main(String[] args) throws SQLException {
        //获取连接
        Connection connection = JDBCUtils.getConnection();
        //拼写登录查询的SQL语句
        //注意,使用PreparedStatement接口执行SQL,所有参数使用问号占位符
        String sql = "select * from users where username=? and password=?";
        //获取 PreparedStatement 接口实现类对象
        PreparedStatement pst = connection.prepareStatement(sql);
        System.out.println(pst);
        //设置问号占位符的实际参数
        //pst对象的方法 setObject(int 第几个问号,Object 实际参数)
        pst.setObject(1,"tom");
        pst.setObject(2,"1233");
        //执行查询,返回结果集
        //pst对象的方法 executeQuery() 返回ResultSet结果集
        ResultSet rs = pst.executeQuery();
        while (rs.next()){
            System.out.println(rs.getString("username")+"\t"+rs.getString("password"));
        }
        //释放资源
        JDBCUtils.close(connection,pst,rs);
    }
}

连接池操作数据库

C3P0连接池

C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用C3P0连接池需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml

  1. 配置文件
    文件名 c3p0-config.xml不能写错,文件放在src中
参数说明
initialPoolSize初始连接数: 刚创建好连接池的时候准备的连接数量
maxPoolSize最大连接数: 连接池中最多可以放多少个连接
checkoutTimeout最大等待时间: 连接池中没有连接时最长等待时间
maxIdleTime最大空闲回收时间: 连接池中的空闲连接多久没有使用就会回收
<c3p0-config>
    <default-config>
         <!--
           property标签名: 配置的就是数据库连接的四大信息
           name属性: 属性值配置的是 四大信息的名字
           标签体: 配置的是具体的信息内容
         -->
        <!--连接参数-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:端口号/数据库名</property>
        <property name="user">账号</property>
        <property name="password">root</property>

        <!--连接池参数-->
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">10</property>
        <property name="checkoutTimeout">2000</property>
        <property name="maxIdleTime">1000</property>
    </default-config>
</c3p0-config>
  1. C3P0工具类
package com.c3p0Utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * C3P0连接池的工具类
 * 直接获取数据库连接
 * 1:找到接口DataSource的实现类 ComboPooledDataSource
 * 2:配置文件的形式,配置连接池的4大信息
 *  配置文件是xml形式,
 *  标签:
 *  <a name="属性值"> 标签体</a>
 *  配置文件的名字  c3p0-config.xml
 *  文件创建在src目录下
 */
public class C3P0Util {
    //成员位置创建出DataSource接口的实现类对象
    private static DataSource dataSource = new ComboPooledDataSource();

    //静态方法,直接返回数据库连接对象
    public static Connection getConnection() throws SQLException {
        Connection connection = dataSource.getConnection();
        return connection;
    }

    /**
     * 关闭资源
     * @param con
     * @param stat
     * @param rs
     */
    public static void close(Connection con, Statement stat, ResultSet rs){
        if(rs!=null)
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(stat!=null)
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(con!=null)
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
}

  1. 测试
import com.c3p0Utils.C3P0Util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 测试自定义的c3p0工具类
 * 获取连接
 */
public class C3P0Test {
    public static void main(String[] args) throws SQLException {
        //获取连接池
        Connection connection = C3P0Util.getConnection();
        //获取数据库SQL执行对象
        Statement statement = connection.createStatement();
        //执行查询,获取结果集
        String sql = "select * from category";
        ResultSet set = statement.executeQuery(sql);
        //循环遍历结果集
        while (set.next()){
            System.out.println(set.getString("pid")+"\t"+set.getString("pname"));
        }
    }
}

Druid连接池

Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid(阿里自称)是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。Druid地址:https://github.com/alibaba/druid DRUID连接池使用的jar包: druid-1.0.9.jar

  1. 配置文件
    文件名druid.properties,不能写错,文件放在src中
参数说明
url连接的数据库的位置
username数据库的用户名
password数据库的密码
driverClassName驱动类名。根据url自动识别,这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive最大连接池数量
maxWait获取连接时最大等待时间,单位毫秒。
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:端口号/数据库名
username=账号
password=密码
initialSize=5
maxActive=10
maxWait=3000
  1. 工具类
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/*
    德鲁伊连接池工具类
    步骤:
      读取配置文件
      配置文件数据,加载集合
      工厂类,创建出DataSource接口实现类
 */
public class DruidUtils {
    //类成员位置创建变量
    private  static  DataSource dataSource ;

    //读取配置文件
    static {
        try {
            //类的加载器方式,获取字节输入流
            //本类.class 字节码文件对象->获取加载器
            //类加载器的方法 getResourceAsStream()返回流
            InputStream in = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            //创建集合对象
            Properties prop = new Properties();
            prop.load(in);
            //德鲁伊的工厂类,创建出DataSource接口实现类对象
            //返回值就是DataSource接口实现类
             dataSource =  DruidDataSourceFactory.createDataSource(prop);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
    /*
      方法,返回DataSource接口实现类对象
     */
    public  static  DataSource getDataSource(){
        return dataSource;
    }

    /*
      静态方法,返回数据连接对象
     */
    public static Connection getConnction() throws SQLException {
        return  dataSource.getConnection();
    }
    /*
      方法释放资源
     */
    public static void close(Connection con, Statement stat, ResultSet rs){
        if(rs!=null)
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(stat!=null)
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(con!=null)
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

    }
}
  1. 测试
import com.domain.Student;
import com.druidutils.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/*
 *  测试自定义德鲁伊工具类
 */
public class DruidTest {
    public static void main(String[] args) {
        select();
    }
    /*
       查询数据
       每行数据存储到JavaBean对象
       多个JavaBean对象存储集合List
     */
    public static void select(){
        //声明需要的类型变量
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            //工具类获取连接
            con = DruidUtils.getConnction();
            //查询数据表的SQL
            String sql = "select * from student";
            //获取SQL语句执行对象
            pst = con.prepareStatement(sql);
            //执行查询,返回结果集
            rs = pst.executeQuery();
            //创建集合,存储JavaBean对象
            List<Student> list = new ArrayList<Student>();
            while (rs.next()){
                //创建JavaBean对象
                Student s = new Student();
                s.setSid(rs.getInt("s_id"));
                s.setSname(rs.getString("s_name"));
                //bean对象存储到集合
                list.add(s);
            }
            for(Student stu:list){
                System.out.println(stu);
            }
        }catch (SQLException ex){
            ex.printStackTrace();
        }finally {
            DruidUtils.close(con,pst,rs);
        }
    }
    
    /*
        数据表Student添加数据
     */
    public static void  insert(){
        //声明需要的类型变量
        Connection con = null;
        PreparedStatement pst = null;
        try{
            //工具类获取连接对象
            con = DruidUtils.getConnction();
            //添加数据的SQL
            String sql = "insert into student values(?,?,?,?)";
            //获取SQL语句执行对象
            pst = con.prepareStatement(sql);
            //设置问号占位符的实际参数
            pst.setObject(1,null);
            pst.setObject(2,"李雷");
            pst.setObject(3,55);
            pst.setObject(4,"13900139000");
            int row = pst.executeUpdate();
            System.out.println(row);
        }catch (SQLException ex){
            ex.printStackTrace();
        }finally {
            DruidUtils.close(con,pst,null);
        }
    }
}

JDBCTemplate

JDBC已经能够满足大部分用户最基本的需求,但是在使用JDBC时,必须自己来管理数据库资源如:获取
PreparedStatement,设置SQL语句参数,关闭连接等步骤。JdbcTemplate就是JDBC的封装,目的是使JDBC更加易于使用。 JdbcTemplate处理了资源的建立和释放。它帮助我们避免一些常见的错误,比如忘了总要关闭连接。它运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。

  1. 创建druid.properties连接池配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mysqltest2
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
  1. 连接池工具类
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/*
    德鲁伊连接池工具类
    步骤:
      读取配置文件
      配置文件数据,加载集合
      工厂类,创建出DataSource接口实现类
 */
public class DruidUtils {
    //类成员位置创建变量
    private  static  DataSource dataSource ;

    //读取配置文件
    static {
        try {
            //类的加载器方式,获取字节输入流
            //本类.class 字节码文件对象->获取加载器
            //类加载器的方法 getResourceAsStream()返回流
            InputStream in = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            //创建集合对象
            Properties prop = new Properties();
            prop.load(in);
            //德鲁伊的工厂类,创建出DataSource接口实现类对象
            //返回值就是DataSource接口实现类
             dataSource =  DruidDataSourceFactory.createDataSource(prop);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
    /*
      方法,返回DataSource接口实现类对象
     */
    public  static  DataSource getDataSource(){
        return dataSource;
    }

    /*
      静态方法,返回数据连接对象
     */
    public static Connection getConnction() throws SQLException {
        return  dataSource.getConnection();
    }
    /*
      方法释放资源
     */
    public static void close(Connection con, Statement stat, ResultSet rs){
        if(rs!=null)
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(stat!=null)
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(con!=null)
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
}
  1. 测试
import com.domain.Student;
import com.druidutils.DruidUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/*
   工具: JDBC模版
   核心类:
     JdbcTemplate
   核心类方法:
      update 执行SQL语句 insert update delete
      query 执行查询
      queryForObject 执行查询,返回对象

      JdbcTemplate 类构造方法 (DataSource dataSource)
      new JdbcTemplate(传递DataSource接口实现类对象)
 */
public class JDBCTemplateDemo {
    public static void main(String[] args) {
        query();
    }
    /*
        JdbcTemplate类方法 query() 查询结果,返回集合存储JavaBean
        query方法参数( String sql,BeanPropertyRowMapper bprm,Object...obj )
        bprm: Bean Property Row Mapper

        new BeanPropertyRowMapper<>()
        <Student>泛型: 封装数据的JavaBean的类型
        (Student.class)构造方法的参数: JavaBean对象的class文件对象
          Object obj = Student.class.newInstance();

     */
    public  static  void query(){
        //创建核心类对象,构造方法中,传递DataSource接口实现类
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        //拼写查询SQL
        String sql = "select * from student";
        //执行查询,方法query,第二个参数,传递BeanPropertyRowMapper类的对象
        List<Student> list =  template.query(sql, new BeanPropertyRowMapper<Student>(Student.class));
        for (Student stu :list){
            System.out.println(stu);
        }
    }

    /*
         JdbcTemplate类方法 queryForObject 查询结果返回对象
         queryForObject参数(String sql, Class c, Object...obj)
         sql:执行SQL语句
         c : 查询后返回对象的类型,这个类的class文件对象
         obj: 问号占位符的参数
     */
    public static void queryForObject(){
        //创建核心类对象,构造方法中,传递DataSource接口实现类
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        //拼写查询SQL
        String sql = "select sname from student where sid=?";
        //执行查询,返回对象,字符串
        String str = template.queryForObject(sql,String.class,2);
        System.out.println(str);
    }

    /*
          JdbcTemplate类方法 update,执行SQL语句,返回操作的行数
          int update方法参数(String sql, Object...obj)
          sql: 要执行的SQL语句
          obj: 可变参数,就是SQL语句中的问号占位符的实际参数
     */
    public static void insert(){
        //创建核心类对象,构造方法中,传递DataSource接口实现类
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        //拼写添加SQL语句
        String sql = "insert into student values(?,?,?,?)";
        //调用方法update执行
        int row = template.update(sql,null,"王重阳",20,"13700137000");
        System.out.println(row);
    }
}

ThreadLocal

ThreadLocal该类提供了线程局部(thread-local)变量,用于当前线程中共享数据

/*
    ThreadLocal<T>
       可以帮助我们 完成 在线程中 存储共享数据
          而这个数据 只对当前的线程 有用
          T 代表 我要存储在 当前线程中 数据的类型
      set(T t)  将 一个数据 存储到当前的线程中

      get()  获取当前线程 对应的数据

      threadLocal 可以理解为 代表当前线程的一个Map

      通过案例发现
         当我们调用 threadLocal对象中的set(t) 功能时  其实是将
            当前线程 与  t 进行对应绑定
            键          值

         当我们调用 threadLocal对象中 get() 功能时  其实是
           根据 当前线程 找到对应的 值

      可以保证 某一个数据 在一个线程中 唯一性 安全性

 */
public class ThreadLocalDemo {

    public static void main(String[] args) {
        //main线程
        System.out.println("进入了主线程");

        ThreadLocal<String> threadLocal = new ThreadLocal<>();

        threadLocal.set("主线程");

        System.out.println("主线程中的数据: " + threadLocal.get());
        new Thread(()->{
            System.out.println("在新开的线程中获取ThreadLocal中存储的数据:"+threadLocal.get());
        }).start();

    }
}

ThreadLocal与JDBC的使用

在这里插入图片描述
配置文件druid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:端口号/数据库
username=账号
password=密码
initialSize=5
maxActive=10
maxWait=3000

工具类JDBCUtils

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/*
   完成
     获取连接对象

     以后 工具类 或者 管理类  里面的东西 都是静态的
 */
public class JDBCUtils {


    private static DataSource dataSource;

    // 我们还没有将 配置信息 传入 dataSource
    // 一次就好
    // 使用静态代码块 完成 读取配置信息操作
    static{
          try{

              Properties pp = new Properties();

//              FileInputStream inputStream = new FileInputStream("day06/src/druid.properties");

              InputStream resourceAsStream = JDBCUtils.class
                      .getResourceAsStream("/druid.properties");

              pp.load(resourceAsStream);

              // 阿里团队 做了一个操作 DruidDataSourceFactory帮你完成 注入配置信息  但是需要一个条件带有配置的Properties对象
              dataSource = DruidDataSourceFactory.createDataSource(pp);


          }catch(Exception e){
              System.out.println("配置信息读取或者创建DataSource失败");
          }
    }


    public static Connection getConnection(){
        // 返回一个Connection对象

        // 由连接池提供

        try {
            return dataSource.getConnection();
        } catch (SQLException e) {

            //将编译期异常转换成运行期异常 抛出
            throw new RuntimeException(e);
        }
    }

    /*
      释放资源 的方方法
     */
    public static void close(ResultSet rs, Statement state,Connection conn){

        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(state!=null){
            try {
                state.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

工具类ConnectionManager

import java.sql.Connection;
import java.sql.SQLException;
public class ConnectionManager {

    // 创建存储 Connection的容器ThreadLocal
    // 保证 在一个线程中连接对象的唯一性  安全性
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    private static Connection connection;

    public static Connection getConnection(){

        // 获取当前线程对象容器 中存储的连接对象
        connection=threadLocal.get();

        if(connection==null){//第一次获取的时候 没有 应该设置进去
            //从连接池中获取  并存储在threadLocal对象中
            connection = JDBCUtils.getConnection();
            // 存储在threadLocal中
            threadLocal.set(connection);

         }

         return connection;
    }

    // 所有关于 Connection中操作事务的方法 都给封装一下
    /*
      开启事务
     */
    public static void begin(){

        try {
            getConnection().setAutoCommit(false);
        } catch (SQLException e) {
            System.out.println("开启失败异常");
        }
    }

    /*
     提交事务
    */
    public static void commit(){

        try {
            getConnection().commit();
        } catch (SQLException e) {
            System.out.println("提交事务异常");
        }
    }

    /*
    回滚事务
   */
    public static void rollback(){

        try {
            getConnection().rollback();
        } catch (SQLException e) {
            System.out.println("回滚事务异常");
        }
    }

    /*
      释放 资源
  */
    public static void close(){

      JDBCUtils.close(null,null,getConnection());
    }
}

web层WebApp

import java.util.Scanner;

/*
   视图层 展示层
       给用户交互
 */
public class WebApp {

    public static void main(String[] args) {
        System.out.println("欢迎来到银行");

        System.out.println("请完成转账操作:");
        //键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入汇款方:");
        String fromName = sc.next();
        System.out.println("请录入收款方:");
        String toName = sc.next();
        System.out.println("请录入金额:");
        double money = sc.nextDouble();
        // 交给 service
        new AccountService().tranAccount(fromName,toName,money);

    }
}

service层

/*
  业务层 service层
 */
public class AccountService {

    /*
      转账 方法
     */
    public void tranAccount(String fromName,String toName,double money){
        // 初始化一个dao对象
        AccountDao accountDao = new AccountDao();
        try{
            // 开启事务
            ConnectionManager.begin();

            // 执行转账操作
            //需要调用dao层内容
            // 减钱
            accountDao.payMoney(fromName,money);
            //加钱
            accountDao.inMoney(toName,money);

            // OK 就提交
            ConnectionManager.commit();
            System.out.println("转账成功");
        }catch(Exception e){
            //失败回滚
            ConnectionManager.rollback();
            System.out.println("转账失败");
                
        }finally {
             ConnectionManager.close();
        }
    }
}

dao层

import java.sql.PreparedStatement;
import java.sql.SQLException;

/*
  这个dao只操作 account表
 */
public class AccountDao {

    /**
     * 完成转账操作中
     *   汇款 中的减钱操作
     * @param fromName  汇款方
     * @param money     汇款金额
     */
    public void payMoney( String fromName, double money) throws Exception{
        // 连接数据库 完成 减钱操作
        // 获取连接对象  conn

        // 获取语句执行平台   安全更高
        String sql = "update account set money=money-? where name = ?";

        PreparedStatement ps = ConnectionManager.getConnection().prepareStatement(sql);

        //执行之前要赋值
        ps.setDouble(1,money);
        ps.setString(2,fromName);

        //执行
        int row = ps.executeUpdate();

        if(row==0){
            // 说明 汇款方不存在  产生一个异常
            throw new SQLException("汇款方不存在");
        }
        //释放
        JDBCUtils.close(null,ps,null);
    }


    /**
     * 完成转账操作中
     *   汇款 中的加钱操作
     * @param toName    收款方
     * @param money     汇款金额
     */
    public void inMoney( String toName, double money) throws Exception{
        // 连接数据库 完成 减钱操作
        // 获取连接对象  conn

        // 获取语句执行平台   安全更高
        String sql = "update account set money=money+? where name = ?";

        PreparedStatement ps =  ConnectionManager.getConnection().prepareStatement(sql);

        //执行之前要赋值
        ps.setDouble(1,money);
        ps.setString(2,toName);

        //执行
        int row = ps.executeUpdate();

        if(row==0){
            // 说明 收款方不存在  产生一个异常
            throw new SQLException("收款方不存在");
        }
        //释放
        JDBCUtils.close(null,ps,null);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值