06_jdbc

1.编写步骤

在这里插入图片描述

补充:ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用 者在程序中只需要调用ODBC API,由 ODBC 驱动程序将调用转换成为对特定的数据库的调用请求。

2.基本连接

详细迭代过程见代码

idea的话,用getResourceAsStream方法读取配置文件默认是在src下读的,而用FileInputStream读取的话分两种情况:在单元测试中,默认是在module下读的,而在main方法中,默认是在project下读的

@Test
public void testConnection5() throws Exception {
    //1.加载配置文件
    InputStream is =
        connection.class.getClassLoader().getResourceAsStream("jdbc.properties");
    //获取一个类加载器也可以写ClassLoader.getSystemClassLoader()
    Properties pros = new Properties();
    pros.load(is);
    //2.读取配置信息
    String user = pros.getProperty("user");
    String password = pros.getProperty("password");
    String url = pros.getProperty("url");
    String driverClass = pros.getProperty("driverClass");
    //3.加载驱动
    Class.forName(driverClass);
    //4.获取连接
    Connection conn = DriverManager.getConnection(url,user,password);
    System.out.println(conn);
}

在这里插入图片描述

3.url与账户

  • MySQL的连接URL编写方式:
    • jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
    • jdbc:mysql://localhost:3306/xxxxx
    • jdbc:mysql://localhost:3306/xxxxx?useUnicode=true&characterEncoding=utf8(如果JDBC
      程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
    • jdbc:mysql://localhost:3306/xxxxx?user=root&password=123456
  • Oracle 9i的连接URL编写方式:
    • jdbc:oracle:thin:@主机名称:oracle服务端口号:数据库名称
    • jdbc:oracle:thin:@localhost:1521:xxxxx
  • SQLServer的连接URL编写方式:
    • jdbc:sqlserver://主机名称:sqlserver服务端口号:DatabaseName=数据库名称
    • jdbc:sqlserver://localhost:1433:DatabaseName=xxxxx

user,password可以用“属性名=属性值”方式告诉数据库 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接

mysql8url需要添加:?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false

String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false";

4.操作访问数据库

在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:

  • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
  • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
  • CallableStatement:用于执行 SQL 存储过程

使用Statement操作数据表的弊端

  • int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
  • ResultSet executeQuery(String sql):执行查询操作SELECT

问题一:存在拼串操作,繁琐 问题二:存在SQL注入问题

PreparedStatement的使用

封装conn
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @Author: rokned
 * @create: 2022/3/29
 */
public class connection {
    public static Connection Getconn() throws IOException, ClassNotFoundException, SQLException {
        //1.加载配置文件
        InputStream is =
            ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        //2.读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //3.加载驱动
        Class.forName(driverClass);
        //4.获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        return  conn;
    }

    public static void closeResource(Connection conn, PreparedStatement ps){
        //资源关闭
        try {
            if(ps != null)
                ps.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(conn != null)
                conn.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public  static void closeResource(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if(ps != null)
                ps.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(conn != null)
                conn.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(rs != null)
                rs.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

增、删、改操作
@Test
//增
public void testInert() {
    Connection conn = null;
    PreparedStatement ps = null;
    try {
        conn = connection.Getconn();
        //预编译sql语句
        String sql  = "insert into customers(name,email,birth)values(?,?,?)";
        ps =  conn.prepareStatement(sql);
        //填充占位符
        ps.setString(1,"芜湖");
        ps.setString(2,"wuhu@qq.com");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse("1000-01-01");
        ps.setDate(3,new java.sql.Date(date.getTime()));
        //执行
        ps.execute();
    }catch (Exception e){
        e.printStackTrace();
    }
    finally {
        connection.closeResource(conn,ps);
    }
}


@Test
//改
public void testupdate(){
    Connection conn = null;
    PreparedStatement ps = null;
    try{
        conn = connection.Getconn();
        String sql = "update customers set name = ? where id = ?";
        ps = conn.prepareStatement(sql);
        ps.setObject(1,"起飞");
        ps.setObject(2,"19");
        ps.execute();
    }catch (Exception e){
        e.printStackTrace();
    }
    finally {
        connection.closeResource(conn,ps);
    }
}

@Test
//删
public void testdelete(){
    Connection conn = null;
    PreparedStatement ps = null;
    try{
        conn = connection.Getconn();
        String sql = "delete from customers where id = ?";
        ps = conn.prepareStatement(sql);
        ps.setObject(1,19);
        ps.execute();
    }catch (Exception e){
        e.printStackTrace();
    }
    finally {
        connection.closeResource(conn,ps);
    }
}
@Test
public void testselect(){
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try{
        conn = connection.Getconn();
        String sql = "select name,email from customers where id = ?";
        ps = conn.prepareStatement(sql);
        ps.setObject(1,20);
        //得到结果集:ResultSet
        rs = ps.executeQuery();
        //处理结果集
        customers customer = new customers();
        if(rs.next()){
            customer.setName(rs.getString(1));
            customer.setEmail(rs.getString(2));
            System.out.println(customer);
        }
    }catch (Exception e){
        e.printStackTrace();
    }
    finally {
        connection.closeResource(conn,ps,rs);
    }
}

5.ResultSet与ResultSetMetaData

ResultSet

Java与数据库交互涉及到的相关Java API中的索引都从1开始。

  • ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。

在这里插入图片描述

ResultSetMetaData

  • 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
  • ResultSetMetaData meta = rs.getMetaData();
    • getColumnName(int column):获取指定列的名称
    • getColumnLabel(int column):获取指定列的别名
    • getColumnCount():返回当前 ResultSet 对象中的列数。
    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
    • isNullable(int column):指示指定列中的值是否可以为 null。
    • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

6.BLOB类型

  • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
  • MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)

在这里插入图片描述

插入

//获取连接
Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符
ps.setString(1, "ywj");
ps.setString(2, "ywj@126.com");
ps.setDate(3, new Date(new java.util.Date().getTime()));
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("ywj.png");
ps.setBlob(4, fis);
//执行
ps.execute();
fis.close();
JDBCUtils.closeResource(conn, ps);

修改

Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png");
ps.setBlob(1, fis);
ps.setInt(2, 25);
ps.execute();
fis.close();
JDBCUtils.closeResource(conn, ps);

读取

String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();
if(rs.next()){
    Integer id = rs.getInt(1);
    String name = rs.getString(2);
    String email = rs.getString(3);
    Date birth = rs.getDate(4);
    Customer cust = new Customer(id, name, email, birth);
    System.out.println(cust);
    //读取Blob类型的字段
    Blob photo = rs.getBlob(5);
    InputStream is = photo.getBinaryStream();
    OutputStream os = new FileOutputStream("c.jpg");
    byte [] buffer = new byte[1024];
    int len = 0;
    while((len = is.read(buffer)) != -1){
        os.write(buffer, 0, len);
    }
    JDBCUtils.closeResource(conn, ps, rs);
    if(is != null){
        is.close();
    }
    if(os != null){
        os.close();
    }
}

7.批量插入

  • addBatch(String):添加需要批量处理的SQL语句或是参数;
  • executeBatch():执行批量处理语句;
  • clearBatch():清空缓存的数据
/*
* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
* 修改2:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
* ?rewriteBatchedStatements=true 写在配置文件的url后面
* 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
* Version1
*/
@Test
public void testInsert1() throws Exception{
    long start = System.currentTimeMillis();
    Connection conn = JDBCUtils.getConnection();
    String sql = "insert into goods(name)values(?)";
    PreparedStatement ps = conn.prepareStatement(sql);
    for(int i = 1;i <= 1000000;i++){
        ps.setString(1, "name_" + i);
        //1.“攒”sql
        ps.addBatch();
        if(i % 500 == 0){
            //2.执行
            ps.executeBatch();
            //3.清空
            ps.clearBatch();
        }
    }
    long end = System.currentTimeMillis();
    System.out.println("花费的时间为:" + (end - start));//20000条:625
    //1000000条:14733
    JDBCUtils.closeResource(conn, ps);
}

/*
* 使用Connection 的 setAutoCommit(false) / commit()
* Version2
*/
@Test
public void testInsert2() throws Exception{
    long start = System.currentTimeMillis();
    Connection conn = JDBCUtils.getConnection();
    //1.设置为不自动提交数据
    conn.setAutoCommit(false);
    String sql = "insert into goods(name)values(?)";
    PreparedStatement ps = conn.prepareStatement(sql);
    for(int i = 1;i <= 1000000;i++){
        ps.setString(1, "name_" + i);
        //1.“攒”sql
        ps.addBatch();
        if(i % 500 == 0){
            //2.执行
            ps.executeBatch();
            //3.清空
            ps.clearBatch();
        }
    }
    //2.提交数据
    conn.commit();
    long end = System.currentTimeMillis();
    System.out.println("花费的时间为:" + (end - start));//1000000条:4978
    JDBCUtils.closeResource(conn, ps);
}

8.事务处理

JDBC程序中为了让多个 SQL 语句作为一个事务执行:

  • 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
  • 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
  • 在出现异常时,调用 rollback(); 方法回滚事务
public void testJDBCTransaction() {
    Connection conn = null;
    try {
        // 1.获取数据库连接
        conn = JDBCUtils.getConnection();
        // 2.开启事务
        conn.setAutoCommit(false);
        // 3.进行数据库操作
        String sql1 = "update user_table set balance = balance - 100 where user = ?";
        update(conn, sql1, "AA");
        // 模拟网络异常
        //System.out.println(10 / 0);
        String sql2 = "update user_table set balance = balance + 100 where user = ?";
        update(conn, sql2, "BB");
        // 4.若没有异常,则提交事务
        conn.commit();
    } catch (Exception e) {
        e.printStackTrace();
        // 5.若有异常,则回滚事务
        try {
            conn.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    } finally {
        try {
            //6.恢复每次DML操作的自动提交功能
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //7.关闭连接
        JDBCUtils.closeResource(conn, null, null);
    }
}
//使用事务以后的通用的增删改操作(version 2.0)
public void update(Connection conn ,String sql, Object... args) {
    PreparedStatement ps = null;
    try {
        // 1.获取PreparedStatement的实例 (或:预编译sql语句)
        ps = conn.prepareStatement(sql);
        // 2.填充占位符
        for (int i = 0; i < args.length; i++) {
            ps.setObject(i + 1, args[i]);
        }
        // 3.执行sql语句
        ps.execute();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 4.关闭资源
        JDBCUtils.closeResource(null, ps);
    }
}

9.mysql隔离级别设置

每启动一个 mysql 程序, 就会获得一个单独的数据库连接.

每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别。

#查看当前的隔离级别:
SELECT @@tx_isolation;
#设置当前 mySQL 连接的隔离级别:
set transaction isolation level read committed;
#设置数据库系统的全局的隔离级别:
set global transaction isolation level read committed;

10.DAO

结构

在这里插入图片描述

在这里插入图片描述

BaseDAO

/**
* 定义一个用来被继承的对数据库进行基本操作的Dao
*/
public abstract class BaseDao<T> {
    //使用DBUtils
    private QueryRunner queryRunner = new QueryRunner();
    // 定义一个变量来接收泛型的类型
    private Class<T> type;
    // 获取T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定
    public BaseDao() {
        // 获取子类的类型
        //例:此时获取BookDaoImpl类,因为是BookDaoImpl继承调用的
        Class clazz = this.getClass();
        // 获取父类的类型
        // getGenericSuperclass()用来获取当前类的父类的类型 ParameterizedType表示的是带泛型的类型
        //例:此时获取得是BaseDao<Book>
        ParameterizedType parameterizedType = (ParameterizedType)
            clazz.getGenericSuperclass();
        // 获取具体的泛型类型 getActualTypeArguments获取具体的泛型的类型 这个方法会返回一个Type的数组
        Type[] types = parameterizedType.getActualTypeArguments();
        // 获取具体的泛型的类型·
        //此时获取的是Book	
        this.type = (Class<T>) types[0];
    }
    /**
* 通用的增删改操作
*
* @param sql
* @param params
* @return
*/
    public int update(Connection conn,String sql, Object... params) {
        int count = 0;
        try {
            count = queryRunner.update(conn, sql, params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }
    /**
* 获取一个对象
*
* @param sql
* @param params
* @return
*/
    public T getBean(Connection conn,String sql, Object... params) {
        T t = null;
        try {
            t = queryRunner.query(conn, sql, new BeanHandler<T>(type), params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return t;
    }
    /**
* 获取所有对象
*
* @param sql
* @param params
* @return
*/
    public List<T> getBeanList(Connection conn,String sql, Object... params) {
        List<T> list = null;
        try {
            list = queryRunner.query(conn, sql, new BeanListHandler<T>(type),
                                     params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }
    /**
* 获取一个但一值得方法,专门用来执行像 select count(*)...这样的sql语句
*
* @param sql
* @param params
* @return
*/
    public Object getValue(Connection conn,String sql, Object... params) {
        Object count = null;
        try {
            // 调用queryRunner的query方法获取一个单一的值
            count = queryRunner.query(conn, sql, new ScalarHandler<>(), params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }
}

其他业务DAO省略

Impl

实现业务层

//父类泛型覆盖,然后通过获取父类泛型得到对象类型
public class BookDaoImpl extends BaseDao<Book> implements BookDao {
    @Override
    public List<Book> getBooks(Connection conn) {
        List<Book> beanList = null;
        // 写sql语句
        String sql = "select id,title,author,price,sales,stock,img_path imgPath from books";
        // 调用BaseDao中得到一个List的方法
        beanList = getBeanList(conn,sql);
        return beanList;
    }
    //...实现其他业务,同理
}

Bean

和数据库中字段对应即可

package com.atguigu.bookstore.beans;
/**
* 用户类
*
*/
public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
}

11.数据库连接池

DBCP数据库连接池

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程 序独立使用。

该连接池依赖该组织下的另一个开源系统:Commonpool。如需使用该连接池实现,应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现
  • Commons-pool.jar:连接池实现的依赖库

在这里插入图片描述

//方式一
public static Connection getConnection3() throws Exception {
    BasicDataSource source = new BasicDataSource();
    source.setDriverClassName("com.mysql.jdbc.Driver");
    source.setUrl("jdbc:mysql:///test");
    source.setUsername("root");
    source.setPassword("abc123");
    source.setInitialSize(10);
    Connection conn = source.getConnection();
    return conn;
}

//方式二
private static DataSource source = null;
static{
    try {
        Properties pros = new Properties();
        InputStream is =
            DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");
        pros.load(is);
        //根据提供的BasicDataSourceFactory创建对应的DataSource对象
        source = BasicDataSourceFactory.createDataSource(pros);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static Connection getConnection4() throws Exception {
    Connection conn = source.getConnection();
    return conn;
}

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=123456
initialSize=10

Druid

在这里插入图片描述

public class TestDruid {
    public static void main(String[] args) throws Exception {
        Properties pro = new Properties();
        pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=20
maxWait=1000
filters=wall

12.Apache-DBUtils实现CRUD操作

DbUtils

在这里插入图片描述

在这里插入图片描述

QueryRunner类

该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少 编码量。

  • public int update(Connection conn, String sql, Object… params) throws SQLException
    • 用来执行 一个更新(插入、更新或删除)操作。
  • public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException
    • 只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的 键值
  • public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException
    • INSERT, UPDATE, or DELETE语句
  • public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException
    • 只支持INSERT语句
  • public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException
    • 执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句 的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
// 测试添加
@Test
public void testInsert() throws Exception {
    QueryRunner runner = new QueryRunner();
    Connection conn = JDBCUtils.getConnection3();
    String sql = "insert into customers(name,email,birth)values(?,?,?)";
    int count = runner.update(conn, sql, "he", "he@qq.com", "1992-09-08");
    System.out.println("添加了" + count + "条记录");
    JDBCUtils.closeResource(conn, null);
}
// 测试删除
@Test
public void testDelete() throws Exception {
    QueryRunner runner = new QueryRunner();
    Connection conn = JDBCUtils.getConnection3();
    String sql = "delete from customers where id < ?";
    int count = runner.update(conn, sql,3);
    System.out.println("删除了" + count + "条记录");
    JDBCUtils.closeResource(conn, null);
}

ResultSetHandler接口及实现类

  • 该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
  • ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
  • 接口的主要实现类:
    • ArrayHandler:把结果集中的第一行数据转成对象数组。
    • ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
    • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
    • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
    • ColumnListHandler:将结果集中某一列的数据存放到List中。
    • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map 里,其key为指定的key。
    • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
    • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
    • ScalarHandler:查询单个值对象
/*
* 测试查询:查询一条记录
*
* 使用ResultSetHandler的实现类:BeanHandler
*/
@Test
public void testQueryInstance() throws Exception{
    QueryRunner runner = new QueryRunner();
    Connection conn = JDBCUtils.getConnection3();
    String sql = "select id,name,email,birth from customers where id = ?";
    BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);
    Customer customer = runner.query(conn, sql, handler, 23);
    System.out.println(customer);
    JDBCUtils.closeResource(conn, null);
}
/*
* 测试查询:查询多条记录构成的集合
*
* 使用ResultSetHandler的实现类:BeanListHandler
*/
@Test
public void testQueryList() throws Exception{
    QueryRunner runner = new QueryRunner();
    Connection conn = JDBCUtils.getConnection3();
    String sql = "select id,name,email,birth from customers where id < ?";
    //
    BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
    List<Customer> list = runner.query(conn, sql, handler, 23);
    list.forEach(System.out::println);
    JDBCUtils.closeResource(conn, null);
}
/*
* 如何查询类似于最大的,最小的,平均的,总和,个数相关的数据,
* 使用ScalarHandler
*
*/
@Test
public void testQueryValue() throws Exception{
    QueryRunner runner = new QueryRunner();
    Connection conn = JDBCUtils.getConnection3();
    //测试一:
    // String sql = "select count(*) from customers where id < ?";
    // ScalarHandler handler = new ScalarHandler();
    // long count = (long) runner.query(conn, sql, handler, 20);
    // System.out.println(count);
    //测试二:
    String sql = "select max(birth) from customers";
    ScalarHandler handler = new ScalarHandler();
    Date birth = (Date) runner.query(conn, sql, handler);
    System.out.println(birth);
    JDBCUtils.closeResource(conn, null);
}

其他

Java与SQL对应数据类型转换表

在这里插入图片描述

通用PreparedStatement

//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)
public void update(String sql,Object ... args){
    Connection conn = null;
    PreparedStatement ps = null;
    try {
        //1.获取数据库的连接
        conn = JDBCUtils.getConnection();
        //2.获取PreparedStatement的实例 (或:预编译sql语句)
        ps = conn.prepareStatement(sql);
        //3.填充占位符
        for(int i = 0;i < args.length;i++){
            ps.setObject(i + 1, args[i]);
        }
        //4.执行sql语句
        ps.execute();
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        //5.关闭资源
        JDBCUtils.closeResource(conn, ps);
    }
}
// 通用的针对于不同表的查询:返回一个对象 (version 1.0)
//只查询一个结果,不能返回多条记录
public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
        // 1.获取数据库连接
        conn = JDBCUtils.getConnection();
        // 2.预编译sql语句,得到PreparedStatement对象
        ps = conn.prepareStatement(sql);
        // 3.填充占位符
        for (int i = 0; i < args.length; i++) {
            ps.setObject(i + 1, args[i]);
        }
        // 4.执行executeQuery(),得到结果集:ResultSet
        rs = ps.executeQuery();
        // 5.得到结果集的元数据:ResultSetMetaData
        ResultSetMetaData rsmd = rs.getMetaData();
        // 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
        int columnCount = rsmd.getColumnCount();
        if (rs.next()) {
            T t = clazz.newInstance();
            for (int i = 0; i < columnCount; i++) {// 遍历每一个列
                // 获取列值
                Object columnVal = rs.getObject(i + 1);
                // 获取列的别名:列的别名,使用类的属性名充当
                String columnLabel = rsmd.getColumnLabel(i + 1);
                // 6.2使用反射,给对象的相应属性赋值
                Field field = clazz.getDeclaredField(columnLabel);
                field.setAccessible(true);
                field.set(t, columnVal);
            }
            return t;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 7.关闭资源
        JDBCUtils.closeResource(conn, ps, rs);
    }
    return null;
}
// 通用的针对于不同表的查询:返回一个集合 (version 2.0)
//返回多条记录,放入集合
public <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
        // 1.获取数据库连接
        conn = JDBCUtils.getConnection();
        // 2.预编译sql语句,得到PreparedStatement对象
        ps = conn.prepareStatement(sql);
        // 3.填充占位符
        for (int i = 0; i < args.length; i++) {
            ps.setObject(i + 1, args[i]);
        }
        // 4.执行executeQuery(),得到结果集:ResultSet
        rs = ps.executeQuery();
        // 5.得到结果集的元数据:ResultSetMetaData
        ResultSetMetaData rsmd = rs.getMetaData();
        // 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
        int columnCount = rsmd.getColumnCount();
        //创建集合对象
        ArrayList<T> list = new ArrayList<T>();
        //if改成while
        while (rs.next()) {
            T t = clazz.newInstance();
            for (int i = 0; i < columnCount; i++) {// 遍历每一个列
                // 获取列值
                Object columnVal = rs.getObject(i + 1);
                // 获取列的别名:列的别名,使用类的属性名充当
                String columnLabel = rsmd.getColumnLabel(i + 1);
                // 6.2使用反射,给对象的相应属性赋值
                Field field = clazz.getDeclaredField(columnLabel);
                field.setAccessible(true);
                field.set(t, columnVal);
            }
            //添加入集合
            list.add(t);
        }
        //返回集合
        return list
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 7.关闭资源
        JDBCUtils.closeResource(conn, ps, rs);
    }
    return null;
}

数据库驱动

5.1.37用于批量插入

5.1.7正常使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值