后端开发——JDBC的学习(三)

本篇继续对JDBC进行总结:

①通过Service层与Dao层实现转账的练习;

②重点:由于每次使用连接就手动创建连接,用完后就销毁,这样会导致资源浪费,因此引入连接池,练习连接池的使用;

③实现一个工具类,不用每次都手写获取连接以及配置数据库要素等,并且对工具类进行优化;然后使用连接池以及工具类对前部分转账部分的练习进行优化;

④对于工具类只封装好了1.注册驱动2.创建连接8.回收资源,因此3.4.5.6.7.这五步没有完成;因此需要用高级应用层封装对这五步进行封装;基本每一个数据表都有一个对应的DAO接口以及其实现类,对其进行增删改查,但是这些操作重复性很高,所以可以抽取出公共的代码,然后给这些DAO的实现类可以抽取一个公共的父类,称为BaseDao; 对于查询操作需要用executeQuery,增删改操作需要用executeUpdate,所以增删改一体,查询一体;

后面会继续更新Mybatis简化JDBC的操作;

以下代码可以直接复制到idea中运行,整体的位置如下:(注意导入druid以及jdbc jar包)

代码一:转账的练习

包含两部分代码,一部分是Service层一部分是Dao层;

java 复制代码
package data_test7;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

//TODO 此类是对bank表的一些操作;
public class BankDao {
    //account 加钱的账号,money:加钱的金额;这里需要设计jdbc因为是对数据库中的表中数据进行操作:
    public  void add(String account,int money,Connection connection)throws Exception{
        //此处就不需要再创建链接了,为了保证同一个事务,需要使用一样的连接才行;
        //Class.forName("com.mysql.cj.jdbc.Driver");
        //Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc_test", "root", "dir99");
        String sql="update t_bank set money=money+? where account=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,money);
        preparedStatement.setObject(2,account);
        int i = preparedStatement.executeUpdate();
        preparedStatement.close();
        //connection.close();
        System.out.println("加钱成功!");
    }
    public  void sub(String account,int money,Connection connection)throws Exception{
        //此处就不需要再创建链接了,为了保证同一个事务,需要使用一样的连接才行;
        //Class.forName("com.mysql.cj.jdbc.Driver");
        //Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc_test", "root", "dir99");
        String sql="update t_bank set money=money-? where account=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,money);
        preparedStatement.setObject(2,account);
        int i = preparedStatement.executeUpdate();
        preparedStatement.close();
        //connection.close();
        System.out.println("扣钱成功!");

    }
}
java 复制代码
package data_test7;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;

//TODO 转账测试:
//TODO 银行卡业务方法,调用Dao中的方法;
public class BankService {
    @Test
    public void start() throws Exception {
        //hello给hi转账500块:
        transfer("hi","hello",500);
    }

    public void transfer(String addAccount,String subAccount,int money) throws Exception {
        BankDao bankDao=new BankDao();
        //注意这种方法不准确,因为当一个账户money为零的时候,再运行加钱还是成功,扣钱会报错。
        // 因此需要统一为一个事务,这个事务包括加钱和扣钱;注意一个事务最基本的要求就是必须是同一个连接对象,connection;
        //TODO 需要加上注册驱动和创建连接以及try-catch并且需要关闭自动提交事务,这样加钱和扣钱就是同一个事务;
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc_test", "root", "dir99");
        try{
            //设置不自动提交事务
            connection.setAutoCommit(false);
            bankDao.add(addAccount,money,connection);//此处需要再传入connection连接;
            bankDao.sub(subAccount,money,connection);
            //事务提交:
            connection.commit();
        }catch(Exception e){
            //事务回滚:
            connection.rollback();
            //抛出异常:
            throw e;
        }finally {
            connection.close();
        }
        //TODO 正常就提交事务,出现异常就回滚到原来的那样,防止扣钱失败,但是加钱成功类似的错误;
        //TODO 总结:事务是添加到业务方法中的;利用try-catch代码块,开始事务和提交事务以及事务回滚;将connection传入dao层即可,dao只负责使用,不用close;


    }
}

代码二:连接池的使用:

java 复制代码
package data_test8;//TODO 数据库连接池:每次使用连接就创建然后销毁的话,会比较浪费资源,因此使用的时候可以在连接池中直接获取,使用完后再放回到连接池中:
// Druid连接池的使用:

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

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

public class DruidUsepart {
    //硬编码方式:
    //直接使用代码设置连接池连接参数方式!
    //1.创建一个druid连接池对象
    //2.设置连接池参数:【必须|非必须】
    //3.获取连接[通用方法,所有连接都一样]
    //4.回收连接
    public void testHard() throws Exception {
        //连接池对象:
        DruidDataSource dataSource=new DruidDataSource();
        //设置参数:
        //必须设置的参数:
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/jdbc_test");
        dataSource.setUsername("root");
        dataSource.setPassword("dir99");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");//帮助注册驱动和创建连接;
        //非必须的参数:
        dataSource.setInitialSize(5);//初始化连接的数量;
        dataSource.setMaxActive(10);//最大数量
        //获取链接:
        Connection connection=dataSource.getConnection();
        //数据库操作
        connection.close();
    }
    public void testSoft() throws Exception {
        //软编码方式:
        //通过读取外部的配置文件的方法实例化druid连接池对象;
        //1.读取配置文件 Properties
        Properties properties=new Properties();
        InputStream resourceAsStream = DruidUsepart.class.getClassLoader().getResourceAsStream("druid.properties");
        properties.load(resourceAsStream);
        //2.使用连接池工具类的工厂模式创建连接池;
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        Connection connection=dataSource.getConnection();
        //数据库操作
        connection.close();
    }
}
//TODO 每次使用连接都这样重新设置比较麻烦,因此想将他们封装到工具类中,每次想使用调用那个类即可;

代码三:工具类的实现以及优化:

普通版:

java 复制代码
package data_test8;

import com.alibaba.druid.pool.DruidDataSourceFactory;

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

//TODO 工具类1.0版本,内部包含一个连接池对象,并且对外提供获取连接和回收连接的方法;
//TODO 工具类中的方法一般设置为静态的,方便外部调用;
/*实现内容:
属性:连接池对象只能实例化一次 实现方法:单例模式或者static代码块(全局只调用一次)
方法:对外提供链接的方法,回收外部传入连接方法
 */
public class jdbc_utils1 {
    private static DataSource dataSource=null;
    static{
        Properties properties=new Properties();
        InputStream resourceAsStream = jdbc_utils1.class.getClassLoader().getResourceAsStream("druid.properties");
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            dataSource= DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //对外提供获取连接方法:
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    //回收方法:
    public static void freeConnection(Connection connection) throws SQLException {
        connection.close();
    }


}

优化后:

java 复制代码
package data_test8;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
//TODO 对于第一个版本的工具类有缺陷,就是在不同方法中调用getconnection方法,返回的是新的连接,并不是一样的连接;
//TODO 利用线程本地变量存储连接信息,确保一个线程的多个方法获取同一个连接connection;
// 优点:实务操作的时候,service和dao 属于同一个线程,不用再传递参数了,大家都可以调用getConnection方法自动获取的是同一个连接;

public class jdbc_util2 {
    private static DataSource dataSource=null;
    private static ThreadLocal<Connection>tl=new ThreadLocal<>();

    static{
        Properties properties=new Properties();
        InputStream resourceAsStream = jdbc_utils1.class.getClassLoader().getResourceAsStream("druid.properties");
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            dataSource= DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //对外提供获取连接方法:
    public static Connection getConnection() throws SQLException {
        //先查看线程本地变量中是否存在
        Connection connection = tl.get();
        if(connection==null){
            //线程本地变量中没有,连接池获取
            connection=dataSource.getConnection();
            //存入线程本地变量
            tl.set(connection);
        }
        return connection;
    }
    //回收方法:
    public static void freeConnection() throws SQLException {
        Connection connection=tl.get();
        if(connection!=null){
            //清空线程本地变量
            tl.remove();
            connection.setAutoCommit(true);//要回归到初始状态,当开启事务的时候是false;
            connection.close();//回收到连接池;
        }
        connection.close();
    }
}

代码四:对转账练习的优化(使用连接池以及工具类)

java 复制代码
package data_test8.daoANDservice;

import data_test8.jdbc_util2;

import java.sql.Connection;
import java.sql.PreparedStatement;

//TODO 此类是对bank表的一些操作;
public class BankDao {
    //account 加钱的账号,money:加钱的金额;这里需要设计jdbc因为是对数据库中的表中数据进行操作:
    public  void add(String account,int money)throws Exception{
        //TODO 可以直接从连接池中获取:
        Connection connection = jdbc_util2.getConnection();
        String sql="update t_bank set money=money+? where account=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,money);
        preparedStatement.setObject(2,account);
        int i = preparedStatement.executeUpdate();
        preparedStatement.close();
        //connection.close();
        System.out.println("加钱成功!");
    }
    public  void sub(String account,int money)throws Exception{
//TODO 直接从连接池中获取
        Connection connection = jdbc_util2.getConnection();
        String sql="update t_bank set money=money-? where account=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,money);
        preparedStatement.setObject(2,account);
        int i = preparedStatement.executeUpdate();
        preparedStatement.close();
        //connection.close();
        System.out.println("扣钱成功!");

    }
}
java 复制代码
package data_test8.daoANDservice;

import data_test8.jdbc_util2;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;

//TODO 转账测试:
//TODO 银行卡业务方法,调用Dao中的方法;
public class BankService {
    @Test
    public void start() throws Exception {
        //hello给hi转账500块:
        transfer("hi","hello",500);
    }

    public void transfer(String addAccount,String subAccount,int money) throws Exception {
        BankDao bankDao=new BankDao();

//TODO 直接从连接池中获取
        Connection connection = jdbc_util2.getConnection();
        try{
            //设置不自动提交事务,开启事务:
            connection.setAutoCommit(false);
            bankDao.add(addAccount,money);
            bankDao.sub(subAccount,money);
            //事务提交:
            connection.commit();
        }catch(Exception e){
            //事务回滚:
            connection.rollback();
            //抛出异常:
            throw e;
        }finally {
            jdbc_util2.freeConnection();
        }
    }
}

代码五:对sql语句进行封装,结合工具类以及连接池对增删改查操作的优化;

java 复制代码
package data_test9;//TODO 首先jdbc中一共有八步:1.注册驱动2.创建连接3.编写sql语句4创建statement5.占位符赋值6.发送sql语句7.结果解析8.回收资源;

import data_test8.jdbc_util2;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

// TODO 对于test8中的工具类只封装好了1.注册驱动2.创建连接8.回收资源,因此3.4.5.6.7.这五步没有完成;因此需要用高级应用层封装对这五步进行封装;
// TODO 基本每一个数据表都有一个对应的DAO接口以及其实现类,对其进行增删改查,但是这些操作重复性很高,所以可以抽取出公共的代码,然后给这些DAO的实现类可以抽取一个公共的父类,称为BaseDao;
//TODO 对于查询操作需要用executeQuery,增删改操作需要用executeUpdate,所以增删改一体,查询一体;
public class BaseDao {

    public int executeUpdate(String sql,Object...params) throws SQLException {
        //TODO 此处是对非查询语句方法的封装:sql是传入的带占位符的sql语句;params是占位符的值,此处用了可变参数(注意,可变参数可以直接当作数组使用);

        Connection connection = jdbc_util2.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for(int i=0;i<params.length;i++){//TODO 注意此处
            preparedStatement.setObject(i+1,params[i]);
        }
        int rows = preparedStatement.executeUpdate();
        //是否回收连接,需要考虑是否是事务,如果将setAutoCommit设置为false代表事务开始,不自动提交,这一系列的操作,要么全部执行成功,要么全部都不成功;如果开启事务了,就不用管,业务层去处理;
        if(connection.getAutoCommit()){//可以通过这个方法来获取是否是false还是true也就是事务是否开启
            //如果为true代表没有开启事务,此时就需要回收;
            jdbc_util2.freeConnection();

        }
        return rows;
    }
    /*
    对于非查询语句的方法返回值是int类型,代表了影响的行数;但是对于查询语句方法返回的是什么类型呢,确实是一个集合,但并不是list<Map>,map没有数据校验机制,并且不支持反射操作;
    其实数据库数据-》对应java的实体类,有一个表:user表,里面有id,name,account,password属性,此时这个表对应一个java类:User类,有id,name,account,password属性,那么表中的一行数据,代表java类的一个对象,------》多行------》List<java实体类>list;
    java实体类可以校验并且支持反射操作;
    那么返回值的类型就是某一个实体类的集合
    <T>声明一个泛型,不确定类型;第一个<T>表示这个方法是一个泛型方法,可以用于指定查询结果的类型;List<T>表示该方法返回的是一个包含T类型的对象的集合,下方的Class<T>由外面传入,确定这个泛型的类型,例如传入一个User类,那么这个泛型就是User类型,还有一个好处就是可以使用这个类的反射机制给属性赋值
    public <T> List<T> executeQuery(Class<T>cla,String sql,Object...params)
    具体实现如下:
     */
    public <T> List<T> executeQuery(Class<T> cla, String sql, Object...params) throws Exception {
        //获取连接:
        Connection connection = jdbc_util2.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //占位符赋值:
        if(params!=null&&params.length!=0){
            for(int i=0;i<params.length;i++){
                preparedStatement.setObject(i+1,params[i]);
            }
        }
        //执行sql语句:
        ResultSet resultSet = preparedStatement.executeQuery();
        //结果解析:
        List<T>list=new ArrayList<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        //获取列的数量,也就是属性的数量;
        int columnCount = metaData.getColumnCount();
        while(resultSet.next()){
            T t=cla.newInstance();//利用反射调用类的无参构造函数实例化对象!
            for(int i=1;i<=columnCount;i++){
                //得到本行i列属性的值
                Object object=resultSet.getObject(i);
                //得到本行i列的属性名:
                String columnLabel = metaData.getColumnLabel(i);
                //此时得到了这一列属性名和属性值,也就是给这个类的实例化对象的属性赋值,可以利用反射实现:
                Field field = cla.getDeclaredField(columnLabel);
                field.setAccessible(true);//属性可能是私用的,这样就可以打破private修饰限制,属性可以被设置;
                //给对象的属性赋值:第一个参数是想要赋值的对象,如果属性为静态的,可以为null;第二个参数是属性值:
                field.set(t,object);

            }
            list.add(t);
        }
        //关闭资源:
        resultSet.close();
        preparedStatement.close();
        if(connection.getAutoCommit()){
            //没有事务可以关闭:
            jdbc_util2.freeConnection();
        }
        return list;
    }


}
java 复制代码
package data_test9;

import org.junit.Test;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//TODO 利用新封装的BaseDao类,对增删改查进行优化:
public class better extends BaseDao {//TODO 此处需要继承一下BaseDao这样就有了其中的Update方法;
    public static void main(String[] args) {

    }
    @Test
    public void testInsert() throws Exception {
//        //对于job_grades表:添加A 1500 3000这条数据
//        //1.创建驱动:
//        Class.forName("com.mysql.jdbc.Driver");
//        //2.创建连接:
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb","root","dir99");
//        //3.编写sql语句以及创建prepareStatement
//        String sql="insert into job_grades values(?,?,?)";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,"A");
//        preparedStatement.setObject(2,1500);
//        preparedStatement.setObject(3,3000);
//        //发送sql语句:
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("数据插入成功!");
//        }else{
//            System.out.println("数据插入失败!");
//        }
//        preparedStatement.close();
//        connection.close();
        String sql="insert into job_grades values(?,?,?)";
        int a = executeUpdate(sql, "A", 88888, 66666);//返回影响行数;


    }
    @Test
    public void testDelete()throws Exception{
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="delete from job_grades where grade_level=?";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,"F");
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("删除成功!");
//        }else{
//            System.out.println("删除失败!");
//        }
//        preparedStatement.close();
//
        String sql="delete from job_grades where grade_level=? and lowest_sal=?";
        executeUpdate(sql,"A",88888);

    }
    @Test
    public void testUpdate()throws Exception{
        //对于job_grades表:将刚添加的A 1500 3000这条数据中3000改为9999;
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="update job_grades set highest_sal=? where lowest_sal=?";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,9999);
//        preparedStatement.setObject(2,1500);
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("更新成功!");
//        }else{
//            System.out.println("更新失败!");
//        }
//        preparedStatement.close();
//        connection.close();
        String sql="update job_grades set highest_sal=? where lowest_sal=?";
        int i = executeUpdate(sql,99999,66666);


    }
    @Test
    //注意此处查询想查询所有数据,然后将数据放入到List<Map>list集合中:
    //可知查询结果是一行一行的,返回的是resultSet,然后将一行存入到map中,map(key=列名,value=列的内容)-》List<Map> list;
    //实现思路:遍历每一行数据,一行对应一个map,获取一行的列名和对应的列的属性,装配即可;然后将map装到一个集合当中就完成了;
    public void testSearch()throws Exception{
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="select * from job_grades";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        ResultSet resultSet = preparedStatement.executeQuery();
//        //TODO 获取列的信息对象:避免手动获取每一个列的数据,metaData装的是当前结果集中列的信息对象(它可以根据下角标获取列的名称,也可以获取列的数量);
//        ResultSetMetaData metaData = resultSet.getMetaData();
//        //列的数量:有了它以后就可以水平遍历列:
//        int columnCount = metaData.getColumnCount();
//        List<Map> list=new ArrayList<>();
//        while(resultSet.next()){
//            //一行对应一个map;
//            Map map=new HashMap();
//            //下面这种方式纯手动提取,如果列的个数更多会非常麻烦并且换一个表就得重新写,效率很低;
            map.put("gradelevel",resultSet.getString(1));
            map.put("lowestsal",resultSet.getInt(2));
            map.put("highestsal",resultSet.getInt(3));
//            //新的方法读取每一个属性的数据,自动遍历列,注意要从一开始,和数据区分开
//            for(int i=1;i<=columnCount;i++){
//                //获取对应列的属性值:
//                Object value = resultSet.getObject(i);
//                //要是想加入map中,需要传入key和value,value已经有了,但是key:列名还没有:获取列的名称:这个方法可以获取列的别名,getcolumnname方法会获取列的名称,万一要是起了别名,就找不到了;
//                String columnLabel = metaData.getColumnLabel(i);
//                map.put(columnLabel,value);
//            }
//            list.add(map);
//        }
//        System.out.println(list);
//        for(Object data:list){
//            System.out.println(data);
//        }
//        resultSet.close();
//        preparedStatement.close();
//        connection.close();
        String sql="select * from job_grades";
        Class<Job_grades> clas = Job_grades.class;
        List<Job_grades> a = executeQuery(clas, sql);
        for (Object o:a){
            System.out.println(o);
        }
    }
}
class Job_grades{
    private String grade_level;
    private int lowest_sal;
    private int highest_sal;
    public String toString(){
        return grade_level+" "+lowest_sal+" "+highest_sal;
    }


}
java 复制代码
package data_test9;

import org.junit.Test;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//TODO 利用新封装的BaseDao类,对增删改查进行优化:
public class better extends BaseDao {//TODO 此处需要继承一下BaseDao这样就有了其中的Update方法;
    public static void main(String[] args) {

    }
    @Test
    public void testInsert() throws Exception {
//        //对于job_grades表:添加A 1500 3000这条数据
//        //1.创建驱动:
//        Class.forName("com.mysql.jdbc.Driver");
//        //2.创建连接:
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb","root","dir99");
//        //3.编写sql语句以及创建prepareStatement
//        String sql="insert into job_grades values(?,?,?)";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,"A");
//        preparedStatement.setObject(2,1500);
//        preparedStatement.setObject(3,3000);
//        //发送sql语句:
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("数据插入成功!");
//        }else{
//            System.out.println("数据插入失败!");
//        }
//        preparedStatement.close();
//        connection.close();
        String sql="insert into job_grades values(?,?,?)";
        int a = executeUpdate(sql, "A", 88888, 66666);//返回影响行数;


    }
    @Test
    public void testDelete()throws Exception{
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="delete from job_grades where grade_level=?";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,"F");
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("删除成功!");
//        }else{
//            System.out.println("删除失败!");
//        }
//        preparedStatement.close();
//
        String sql="delete from job_grades where grade_level=? and lowest_sal=?";
        executeUpdate(sql,"A",88888);

    }
    @Test
    public void testUpdate()throws Exception{
        //对于job_grades表:将刚添加的A 1500 3000这条数据中3000改为9999;
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="update job_grades set highest_sal=? where lowest_sal=?";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        preparedStatement.setObject(1,9999);
//        preparedStatement.setObject(2,1500);
//        int i = preparedStatement.executeUpdate();
//        if(i>0){
//            System.out.println("更新成功!");
//        }else{
//            System.out.println("更新失败!");
//        }
//        preparedStatement.close();
//        connection.close();
        String sql="update job_grades set highest_sal=? where lowest_sal=?";
        int i = executeUpdate(sql,99999,66666);


    }
    @Test
    //注意此处查询想查询所有数据,然后将数据放入到List<Map>list集合中:
    //可知查询结果是一行一行的,返回的是resultSet,然后将一行存入到map中,map(key=列名,value=列的内容)-》List<Map> list;
    //实现思路:遍历每一行数据,一行对应一个map,获取一行的列名和对应的列的属性,装配即可;然后将map装到一个集合当中就完成了;
    public void testSearch()throws Exception{
//        Class.forName("com.mysql.jdbc.Driver");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigudb", "root", "dir99");
//        String sql="select * from job_grades";
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//        ResultSet resultSet = preparedStatement.executeQuery();
//        //TODO 获取列的信息对象:避免手动获取每一个列的数据,metaData装的是当前结果集中列的信息对象(它可以根据下角标获取列的名称,也可以获取列的数量);
//        ResultSetMetaData metaData = resultSet.getMetaData();
//        //列的数量:有了它以后就可以水平遍历列:
//        int columnCount = metaData.getColumnCount();
//        List<Map> list=new ArrayList<>();
//        while(resultSet.next()){
//            //一行对应一个map;
//            Map map=new HashMap();
//            //下面这种方式纯手动提取,如果列的个数更多会非常麻烦并且换一个表就得重新写,效率很低;
            map.put("gradelevel",resultSet.getString(1));
            map.put("lowestsal",resultSet.getInt(2));
            map.put("highestsal",resultSet.getInt(3));
//            //新的方法读取每一个属性的数据,自动遍历列,注意要从一开始,和数据区分开
//            for(int i=1;i<=columnCount;i++){
//                //获取对应列的属性值:
//                Object value = resultSet.getObject(i);
//                //要是想加入map中,需要传入key和value,value已经有了,但是key:列名还没有:获取列的名称:这个方法可以获取列的别名,getcolumnname方法会获取列的名称,万一要是起了别名,就找不到了;
//                String columnLabel = metaData.getColumnLabel(i);
//                map.put(columnLabel,value);
//            }
//            list.add(map);
//        }
//        System.out.println(list);
//        for(Object data:list){
//            System.out.println(data);
//        }
//        resultSet.close();
//        preparedStatement.close();
//        connection.close();
        String sql="select * from job_grades";
        Class<Job_grades> clas = Job_grades.class;
        List<Job_grades> a = executeQuery(clas, sql);
        for (Object o:a){
            System.out.println(o);
        }
    }
}
class Job_grades{
    private String grade_level;
    private int lowest_sal;
    private int highest_sal;
    public String toString(){
        return grade_level+" "+lowest_sal+" "+highest_sal;
    }


}
相关推荐
2301_813599551 小时前
Go语言怎么做秒杀系统_Go语言秒杀系统实战教程【实用】
jvm·数据库·python
NCIN EXPE6 小时前
redis 使用
数据库·redis·缓存
MongoDB 数据平台6 小时前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb
lUie INGA6 小时前
在2023idea中如何创建SpringBoot
java·spring boot·后端
极客on之路6 小时前
mysql explain type 各个字段解释
数据库·mysql
代码雕刻家6 小时前
MySQL与SQL Server的基本指令
数据库·mysql·sqlserver
lThE ANDE6 小时前
开启mysql的binlog日志
数据库·mysql
yejqvow126 小时前
CSS如何控制placeholder文字的颜色_使用--placeholder伪元素
jvm·数据库·python
handler016 小时前
从源码到二进制:深度拆解 Linux 下 C 程序的编译与链接全流程
linux·c语言·开发语言·c++·笔记·学习
电子云与长程纠缠6 小时前
UE5 两种方式解决Decal Actor贴花拉伸问题
学习·ue5·游戏引擎