Day 14 JDBC


在这里插入图片描述

1、简单入门 Statement

步骤:
1、注册驱动
2、创建连接
3、创建 Statement对象
4、编写sql语句 并且发送sql语句获得结果集
5、解析结果集
6、释放资源
注意事项 都在写下面代码里了

import com.mysql.cj.jdbc.Driver;

import java.sql.*;
import java.util.Properties;

public class day1 {
    public static void main(String[] args) throws Exception {
        new test();
        new test();
        //注册驱动  不推荐 会注册两次 new Driver中有静态代码块
        //DriverManager.registerDriver(new Driver());
        //new Driver();//不推荐 不能显示出 是什么驱动 如果是8+ 则是com.mysql.cj.jdbc 如果是5+ 则是com.mysql.jdbc
        Class.forName("com.mysql.cj.jdbc.Driver");  //推荐 通过反射获得类加载
        //建立连接 3种方式 ①
//        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
        // ②
        Properties properties=new Properties();
        properties.put("user","ckytest");
        properties.put("password","123456");
//        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test",properties);
        //③
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?user=ckytest&password=123456");
        //创建 mql
        Statement statement = ckytest.createStatement();
        //mql 并发送 获取结果集
        String mysql="select * from u_ser";
        //  statement.executeUpdate();  非DML


        ResultSet resultSet = statement.executeQuery(mysql);
        while(resultSet.next()){
            int anInt = resultSet.getInt(1);
//            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(anInt+"---"+name);
        }
    }
}

2、preparedStatement

步骤:
1、注册驱动
2、创建连接
3、编写sql语句
4、创建preparedStatement 对象并且传入sql语句
5、占位符赋值
从左到右 索引从1开始
6、发送sql语句获得结果集
7、解析结果集
8、释放资源

import com.mysql.cj.jdbc.Driver;
import org.junit.Test;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class test {
    @Test
   public void testinsert() throws  Exception{
       Class.forName("com.mysql.cj.jdbc.Driver");
       Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
       String mysql="insert into u_ser(id,name) values(?,?);";
       PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);
       preparedStatement.setObject(1,3);
       preparedStatement.setObject(2,"yue");
        int i = preparedStatement.executeUpdate();
        if (i>0)
           System.out.println("成功");
        preparedStatement.close();
        ckytest.close();
   }

    @Test
    public void testupdate() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
        String mysql="update u_ser set name=? where id=?;";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);
        preparedStatement.setObject(1,"cui");
        preparedStatement.setObject(2,3);
        int i = preparedStatement.executeUpdate();
        if (i>0)
            System.out.println("成功");
        preparedStatement.close();
        ckytest.close();
    }
    @Test
    public void testdelete() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
        String mysql="delete from u_ser where  id=?;";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);
        //preparedStatement.setObject(1,"cui");
        preparedStatement.setObject(1,3);
        int i = preparedStatement.executeUpdate();
        if (i>0)
            System.out.println("成功");
        preparedStatement.close();
        ckytest.close();
    }

    //查询u_ser表中所有的内容 并保存到 List<map>集合中 key-value
    @Test
    public void testquery() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
        String mysql="select * from u_ser;";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);
        ResultSet resultSet = preparedStatement.executeQuery();
        //得到表信息
        ResultSetMetaData metaData = resultSet.getMetaData();
        //得到列数量
        int columnCount = metaData.getColumnCount();
        List<Map> list=new ArrayList<>();
        while(resultSet.next()) {
            Map map = new HashMap();
            for (int i = 1; i <= columnCount; i++) {
                //获得结果
                Object object = resultSet.getObject(i);
                //获得列名
                String columnLabel = metaData.getColumnLabel(i);
                map.put(columnLabel, object);

            }
            list.add(map);
        }
        System.out.println(list);
        resultSet.close();
        preparedStatement.close();
        ckytest.close();
    }
}

String columnLabel = metaData.getColumnLabel(i);
getColumnLabel 有别名可以获得别名而getColumnName 不能获取别名。
getColumnCount 获取列的数量
getMetaData 获取列的信息

3、主键回显

  /**
     * 
     * 得到自增长的主键
     * 在创建prepareStatement,告知它拿回自增长的主键
     * getGeneratedKeys 得到一个自增长主键的结果 首先通过next 移动光标
     * 之后通过getxx 获取结果,插入一行 肯定只获取一个结果 所以是一行一列 索引为1 即使回显的主键
     */
    @Test
    public void testinsertkey() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");
        String mysql="insert into u_ser(name) values(?);";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql,Statement.RETURN_GENERATED_KEYS);
        preparedStatement.setObject(1,"yue1");
        int i = preparedStatement.executeUpdate();
        if (i>0)
            System.out.println("成功");
        ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
        generatedKeys.next();
        Object id = generatedKeys.getObject(1);
        System.out.println("回显主键:"+id);
        preparedStatement.close();
        ckytest.close();
    }

4、批量操作

在url中添上rewriteBatchedStatements=true,允许批量操作。
sql语句不要加分号
preparedStatement.addBatch();
preparedStatement.executeBatch();

    @Test
    public void testinsert1() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true", "ckytest", "123456");
        String mysql="insert into u_ser(name) values(?)";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql,Statement.RETURN_GENERATED_KEYS);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            preparedStatement.setObject(1,"yue1"+i);
             preparedStatement.executeUpdate();

        }
        long end = System.currentTimeMillis();
        System.out.println("时间为:"+(end-start)/1000+"s"); //14s
        preparedStatement.close();
        ckytest.close();
    }
    @Test
    public void testabatchinsert() throws  Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true", "ckytest", "123456");
        String mysql="insert into u_ser(name) values(?)";
        PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            preparedStatement.setObject(1,"yue"+i);
            preparedStatement.addBatch();
        }
        preparedStatement.executeBatch();
        long end = System.currentTimeMillis();
        System.out.println("时间为:"+(end-start)+"s");//0.77s
        preparedStatement.close();
        ckytest.close();
    }

5、事务

原子性 一致性 隔离性 持久性
事务的发生 必须是在同一个连接中。
对于事务,我们应该在业务层进行开启和关闭。mysql是自动提交业务,我们可以手动开启或者关闭。
比如转账业务,我们可以在业务层获取一个连接,之后将该连接传入加钱和转钱方法,这样可以确保是一个连接。
事务,我们一般使用try,catch,如果成功就提交,捕捉到错误就回滚。

6、Druid

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

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

public class DruidTest {
    public void druid1() throws  Exception{
        //创建连接池对象
        DruidDataSource druidDataSource=new DruidDataSource();
        //一些必要和不必要的选项 url,name,pwd,driver都是必须的 连接池数量这些不是必须的
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
        druidDataSource.setPassword("123456");
        druidDataSource.setUsername("ckytest");
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setInitialSize(5);
        druidDataSource.setMaxActive(10);
        //获得一个连接。
        DruidPooledConnection connection = druidDataSource.getConnection();
        //回收
        connection.close();//如果是连接池 则close代表 回收 而不是关闭连接。
    }
    public void druid2() throws  Exception{

        //读取配置文件
        Properties properties=new Properties();
        //只要在src下 就可以使用类加载器
        InputStream resourceAsStream = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
        properties.load(resourceAsStream);//加载到properties中
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        //获得一个连接。
        Connection connection = dataSource.getConnection();
        //回收
        connection.close();//如果是连接池 则close代表 回收 而不是关闭连接。
    }
}

Url=jdbc:mysql://127.0.0.1:3306/test
Password=123456
Username=ckytest
DriverClassName=com.mysql.cj.jdbc.Driver

6.1 工具类V1

每次都去初始化连接池太麻烦了,我们封装一个工具类,对外提供一个获取连接和回收连接的方法。

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 DruidUtils {
    //连接池
    private static DataSource dataSource=null;
    static {
        Properties properties=new Properties();
        InputStream resourceAsStream = DruidUtils.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 Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    public void closeConnection(Connection connection){
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

6.2 工具类V2

我们的工具类V1,只是单例模式了连接池,但是每次获取连接都是新的连接。
如果我们在Serve层获得一个连接,这个连接还需要传给Dao层来获取,能不能让同一个线程,Serve层和Dao层获取的都是同一个连接,而不用使用参数传递呢?可以使用线程局部变量。只要一个线程里边的属性就是通用的。

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 DruidUtils {
    //连接池
    private static DataSource dataSource=null;
    private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();
    static {
        Properties properties=new Properties();
        InputStream resourceAsStream = DruidUtils.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 Connection getConnection() throws SQLException {
        Connection connection=threadLocal.get();
        if (connection==null){
            connection = dataSource.getConnection();
            threadLocal.set(connection);
        }
        return connection;
    }
    public void closeConnection() throws Exception{
        Connection connection = threadLocal.get();
        if (connection!=null){
            threadLocal.remove();
            connection.setAutoCommit(true);
            connection.close();
        }
    }
}

6.3

对于Dao层的封装,写一个基础BaseDao,对语句进行封装,可以分为DQL和非DQl两种。

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

public class A {

    public static int  executUpdate(String sql,Object ... args) throws Exception{
        Connection connection = DruidUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i <args.length ; i++) {
            preparedStatement.setObject(i+1,args[i]);
        }
        int i = preparedStatement.executeUpdate();
        if (connection.getAutoCommit()){
            //没有开启事务
            DruidUtils.closeConnection();
        }
        return i;
    }
    public static  <T>  List<T> executQuery(Class<T> tClass,String sql, Object ... args) throws Exception{
        Connection connection = DruidUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        if(args!=null&&args.length>0)
        {
            for (int i = 0; i <args.length ; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
        }
        ResultSet resultSet = preparedStatement.executeQuery();
        //得到表信息
        ResultSetMetaData metaData = resultSet.getMetaData();
        //得到列数量
        int columnCount = metaData.getColumnCount();
        List<T> list=new ArrayList<>();
        while(resultSet.next()) {
            Constructor<T> constructor = tClass.getConstructor();
            T t = constructor.newInstance();
            for (int i = 1; i <= columnCount; i++) {
                //获得结果
                Object object = resultSet.getObject(i);
                //获得列名
                String columnLabel = metaData.getColumnLabel(i);
                Field declaredField = tClass.getDeclaredField(columnLabel);
                declaredField.set(t,object);
            }
            list.add(t);
        }
        if (connection.getAutoCommit()){
            //没有开启事务
            DruidUtils.closeConnection();
        }
        return list;
    }
}

数据库每个表都对应java中的一个实体类,查询时我们返回的是一个装有实体类的集合。

封装过工具类之后的增删改查 简化了很多。

import com.mysql.cj.jdbc.Driver;
import org.junit.Test;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class test {
    @Test
   public void testinsert() throws  Exception{

       String mysql="insert into u_ser(id,name) values(?,?);";
        int a = A.executUpdate(mysql, 50001, "a");
        System.out.println(a);
   }

    @Test
    public void testupdate() throws  Exception{

        String mysql="update u_ser set name=? where id=?;";
        int a = A.executUpdate(mysql, "cui", 1);
        System.out.println(a);
    }
    @Test
    public void testdelete() throws  Exception{

        String mysql="delete from u_ser where  id=?;";
        int a = A.executUpdate(mysql, 1);
        System.out.println(a);
    }

    //查询u_ser表中所有的内容 并保存到 List<map>集合中 key-value
    @Test
    public void testquery() throws  Exception{
        String mysql="select * from u_ser;";
        List<User> users = A.executQuery(User.class, mysql);
        System.out.println(users);
    }


  
}

相关推荐

  1. JDBC*

    2024-03-23 21:40:04       46 阅读
  2. 【第15章】spring-jdbc之JdbcTemplate

    2024-03-23 21:40:04       88 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-23 21:40:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-23 21:40:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-23 21:40:04       87 阅读
  4. Python语言-面向对象

    2024-03-23 21:40:04       96 阅读

热门阅读

  1. 【Docker】Docker官方发布26.0.0社区版

    2024-03-23 21:40:04       33 阅读
  2. Docker 安装 CentOS7 系统

    2024-03-23 21:40:04       37 阅读
  3. 实验7-2-10 简易连连看(PTA)

    2024-03-23 21:40:04       34 阅读
  4. RESTful架构

    2024-03-23 21:40:04       38 阅读
  5. Vue复习

    Vue复习

    2024-03-23 21:40:04      37 阅读
  6. go 基础中的一些坑(2)

    2024-03-23 21:40:04       35 阅读
  7. 氧化铝电容的工艺结构原理及选型参数总结

    2024-03-23 21:40:04       41 阅读
  8. Python之functools模块之lru_cache

    2024-03-23 21:40:04       43 阅读
  9. 智能新纪元:AI大模型学习的奥秘与挑战

    2024-03-23 21:40:04       40 阅读
  10. 274. H 指数

    2024-03-23 21:40:04       35 阅读
  11. VMware Workstation17安装

    2024-03-23 21:40:04       45 阅读
  12. 【保姆级讲解Linux常见命令】

    2024-03-23 21:40:04       39 阅读