zoukankan      html  css  js  c++  java
  • Java连接数据库JDBC

    前言

    在Python和Golang我们可以使用pip install和go get 去下载开发中使用到的开源的第三方包,以实现企业级应用的开发;

    在Java中使用一系列的JAR包通常用于归档大量的Java类文件、相关的元数据和资源(文本、图片等)文件到1个文件中,以便开发Java平台应用软件或库。

    帮助我们实现功能丰富、复杂的企业家应用开发;

    JAR(Java Archive/Java归档)包,不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和 JVM 这样的工具直接使用。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.mingde</groupId>
        <artifactId>_03_maven_jdbc</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <name>_03_maven_jdbc</name>
        <!--&lt;!&ndash; FIXME change it to the project's website &ndash;&gt;-->
        <!--<url>http://www.example.com</url>-->
        <packaging>jar</packaging>
        <description>MySQL数据库连接测试</description>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <!--junit依赖包-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <!-- jdbc依赖包https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.37</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.18</version>
                <scope>provided</scope>
            </dependency>
            <!--c3p0依赖包-->
            <dependency>
                <groupId>com.mchange</groupId>
                <artifactId>c3p0</artifactId>
                <version>0.9.5.2</version>
            </dependency>
            <!--druid依赖包-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.9</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <configuration>
                        <appendAssemblyId>false</appendAssemblyId>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <archive>
                            <manifest>
                                <!-- 此处指定main方法入口的class -->
                                <mainClass>com.mingde.jdbc.JdbcDemo1</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>assembly</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    pom.xml

    一、JDBC是什么?

    Java Database Connectivity简称JDBC,是Java官方(Sun公司)定义的一套Java程序操作所有关系型数据库的规范(接口)

    各大数据库厂商为了通过Java来推广自己的数据库产品,实现了JDBC规范(接口)并通过JAR包的形式发布出来给Java开发人员使用,就是数据库驱动(driver)。

    现在我们要用Java调MySQL数据库,所以就需要提前下载MySQL提供的的driver,也就是1个JAR包;

    二、JDBC数据库操作 

    DriverManager驱动管理对象:             可以获取数据库连接对象。
    Connection 数据库连接对象: 可以获取执行SQL的对象,可以管理事务操作。
    Statement 执行静态SQL对象: 可以执行数据库的增删改查操作
    PrepareStatement 执行预编译SQL对象: 可以执行带有?占位符的预编译SQL
    ResultSet 查询结果集对象: 保存封装了MySQL查询结果对象
     

    1.创建表(DML)

    package cn.zhanggen;
    
    import com.mysql.jdbc.CommunicationsException;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    public class App { public static void main(String[] args) { Connection connection = null; Statement statement = null; try { Class.forName("com.mysql.jdbc.Driver"); String dbURL = "jdbc:mysql://192.168.56.18:3306/web?characterEncoding=utf8"; connection = DriverManager.getConnection(dbURL, "zhanggen", "123.com"); statement = connection.createStatement(); String createTable="CREATE TABLE IF NOT EXISTS `staffs`(\n" + "`id` INT UNSIGNED AUTO_INCREMENT KEY COMMENT '用户编号',\n" + "`username` VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',\n" + "`age` TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄',\n" + "`salary` FLOAT(8,2) NOT NULL DEFAULT 0 COMMENT '薪水'\n" + ")ENGINE=INNODB DEFAULT CHARSET=UTF8;"; statement.executeUpdate(createTable); // String sql = "insert into staffs(username,age,salary) values ('马睿',18,999.19),('张景辉',58,999.19);"; // statement.executeUpdate(sql); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { System.out.println("11"); e.printStackTrace(); } finally { if (statement != null) { try { statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }

    2.新增记录

    import java.sql.Connection;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    
    public class Insert01 {
        public static void main(String[] args) throws Exception {
            //1.将MySQL服务器提供的jar包中的Driver接口实现类,注册到JVM
            Driver driver = new com.mysql.jdbc.Driver();
            DriverManager.registerDriver(driver);
    
            //2.通过DriverManager在java工程和MySQL服务器之间建立1个连接通道;
            String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
            Connection conn = DriverManager.getConnection(dbURL, "yourusername", "yourpassword");
    
            //3.在通道中创建1个交通工具
            PreparedStatement ps = conn.prepareStatement("");
    
            //4.通过交通工具将SQL命令推送到MySQL服务器上执行
            String sql = "insert into staffs(username,age,salary) values ('Martin',18,999.19),('Tom',58,999.19);";
    
            //5.执行插入SQL命令
            int counter = ps.executeUpdate(sql);
            System.out.println(counter);
    
            //6.关闭数据库连接资源
            if (conn != null) {
                conn.close();
            }
    
            if (ps != null) {
                ps.close();
            }
    
        }
    
    
    }

    3.更新记录

    import java.sql.Connection;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    
    public class update02 {
        public static void main(String[] args) throws Exception {
            //1.将MySQL服务器提供的jar包中的Driver接口实现类,注册到JVM中
    //        Driver driver = new com.mysql.jdbc.Driver();
    //        DriverManager.registerDriver(driver);
            Class.forName("com.mysql.jdbc.Driver");
    
            //2.通过DriverManager建立数据库连接通道
            String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
            Connection conn = DriverManager.getConnection(dbURL, "用户", "密码");
    
            //3.在通道上创建1个运输SQL的交通工具.
            PreparedStatement ps = conn.prepareStatement("");
    
            //4.使用交通工具运输SQL;
            String sql = "update staffs set age=18 where username='Martin';";
            int couner = ps.executeUpdate(sql);
            System.out.printf("更新了%s条数据\n", couner);
    
            //5.回收数据库资源
            if (conn != null) {
                conn.close();
            }
    
            if (ps != null) {
                ps.close();
            }
    
    
        }
    }

    4.查询

    以上我们使用statement对象的executeUpdate()方法对数据库进行了增、删、该操作。

    使用statement对象的executeQuery()方法可以进行数据库的查询。

    executeQuery()方法执行之后,查询结果会保存在ResultSet对象中。

    JDBC查询结果的获取顺序:先向下移动一行,锁定当前行之后,逐个获取当前行的列。

    ResultSet.next():游标向下移动一行,

    Result.getString(参数):获取当前行的某1列

    package com.mingde;
    
    import java.sql.*;
    
    public class JdbcDemo3 {
        public static void main(String[] args) {
            Connection connection = null;
            Statement statement = null;
            ResultSet resultSet = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
                connection = DriverManager.getConnection(dbURL, "weike", "weike@123");
                statement = connection.createStatement();
                String QuerySQL = "select id,username,age,salary from staffs";
                //executeQuery:JDBC查询API
                resultSet = statement.executeQuery(QuerySQL);
                //游标向下锁定一行
                //boolean next = resultSet.next();
                while (resultSet.next()) {
                    //获取当前行的每个列
                    int id = resultSet.getInt("id");
                    String userName = resultSet.getString("username");
                    int age = resultSet.getInt("age");
                    double salary = resultSet.getDouble("salary");
                    System.out.println(id + "----" + "----" + userName + "----" + age + "--------" + salary);
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (resultSet != null) {
                        resultSet.close();
                    }
                    if (statement != null) {
                        statement.close();
                    }
                    if (connection != null) {
                        connection.close();
                    }
                    
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
    
        }
    } 

    5.查询结果封装到List集合中

    package com.mingde;
    
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    
    public class JdbcDemo4 {
        public static void main(String[] args) {
            List allStaffs = findAll();
            System.out.println(allStaffs.size());
            System.out.println(allStaffs);
    
        }
    
        //封装查询所有记录方法
        private static List findAll() {
            Connection connection = null;
            Statement statement = null;
            ResultSet resultSet = null;
            List<Staff> staffList = new ArrayList<Staff>();
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
                connection = DriverManager.getConnection(dbURL, "weike", "weike@123");
                statement = connection.createStatement();
                String QuerySQL = "select id,username,age,salary from staffs";
                resultSet = statement.executeQuery(QuerySQL);
                while (resultSet.next()) {
                    //创建Staff对象并给属性赋值
                    Staff staff = new Staff();
                    staff.setId(resultSet.getInt("id"));
                    staff.setUsername(resultSet.getString("username"));
                    staff.setAge(resultSet.getInt("age"));
                    staff.setSalary(resultSet.getDouble("salary"));
                    //Staff对象装载到list中
                    staffList.add(staff);
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (resultSet != null) {
                        resultSet.close();
                    }
                    if (statement != null) {
                        statement.close();
                    }
                    if (connection != null) {
                        connection.close();
                    }
    
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            return staffList;
        }
    }
    jdbc查询所有记录封装

    6.查询封装为工具类

    package util;
    
    import java.io.FileReader;
    import java.io.IOException;
    import java.sql.*;
    import java.util.Properties;
    
    public class JDBCUtils {
        //使用静态代码块,加载类时,读取一次配置文件
        private static String dbURL;
        private static String user;
        private static String password;
        private static String driver;
    
        static {
            try {
                //加载配置文件
                Properties properties = new Properties();
                //获取src/main/resources的路径/jdbc.properties
                String configFilePath =JDBCUtils.class.getClassLoader().getResource("jdbc.properties").getPath();
                properties.load(new FileReader(configFilePath));
                dbURL = properties.getProperty("url");
                user = properties.getProperty("user");
                password = properties.getProperty("password");
                //注册驱动
                driver = properties.getProperty("driver");
                Class.forName(driver);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        //获取连接,返回连接对象
        public static Connection getConnection() {
            Connection connection = null;
            try {
                connection = DriverManager.getConnection(dbURL, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
    
        //释放数据库资源
        public static void close(Statement statement, Connection connection) {
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //重写释放数据库资源
        public static void close(ResultSet resultSet, Statement statement, Connection connection) {
            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();
                }
            }
        }
    }
    JDBCUtils

    7.SQL预编译和批量执行

    SQL预编译可以防止SQL注入,批量执行可以提升SQL执行的效率;

    我们通过set数据类型,给PrepareStatement对象的占位符赋值。

    package com.mingde;
    
    import java.sql.*;
    
    public class JdbcDemo6 {
        public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
                connection = DriverManager.getConnection(dbURL, "weike", "weike@123");
                //1.定义带?占位符的SQL语句
                String preparedSQL = "select id,username,age,salary from staffs where username=? and age=?";
                //2.把带?占位符的SQL语句先传输到MySQL Server
                preparedStatement = connection.prepareStatement(preparedSQL);
                //3.给第1个? 赋值
                preparedStatement.setString(1, "Martin");
                //4.给第2个? 赋值
                preparedStatement.setInt(2, 18);
                //5.再把参数传输到MySQL Server,
                //6.然后再进行SQL语句和参数的替换
                resultSet = preparedStatement.executeQuery();
                while (resultSet.next()) {
                    //获取当前行的每个列
                    int id = resultSet.getInt("id");
                    String userName = resultSet.getString("username");
                    int age = resultSet.getInt("age");
                    double salary = resultSet.getDouble("salary");
                    System.out.println(id + "----" + "----" + userName + "----" + age + "--------" + salary);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (resultSet != null) {
                        resultSet.close();
                    }
                    if (preparedStatement != null) {
                        preparedStatement.close();
                    }
                    if (connection != null) {
                        connection.close();
                    }
    
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }

    8.jdbc控制事务

    事务:1组包含多个步骤的数据库操作。如果这组业务被事务管理,则这多个步骤要么一起成功,要么一起失败。

    事务包含3个操作:开始事务、提交事务 或者 回归事务。

    connection.setAutoCommit(false):开启事务
    commit():事务
    提交/执行
    rollback:事务回滚
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    public class Transaction05 {
        //jdbc的事务操作
        public static void main(String[] args) throws Exception {
            //1.注册MySQL driver
            Class.forName("com.mysql.jdbc.Driver");
            //2.创建数据库连接
            String dbURL = "jdbc:mysql://192.168.0.98:3306/zhanggen?characterEncoding=utf8";
            Connection conn = DriverManager.getConnection(dbURL, "用户", "密码");
            //3.命令启动事务相当于执行start transaction;
            conn.setAutoCommit(false);
            PreparedStatement ps = conn.prepareStatement("");
            String sql1 = "delete from staffs where username='张根85';";
            String sql2 = "delete from staffs where username='张根86';";
    
            try {
                int count1 = ps.executeUpdate(sql1);
                int count2 = ps.executeUpdate(sql2);
                System.out.println(count1);
                System.out.println(count2);
                conn.commit();
            } catch (SQLException e) {
                //SQL执行出现异常回滚
                System.out.println("回滚了!");
                conn.rollback();
            } finally {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
    
            }
    
    
        }
    }

    三、数据库连接池

    在业务比较繁忙的情况下,客户端频繁发起系统调用创建数据库连接然后再关闭连接,浪费客户端系统资源,也比较耗时。

    在Java中可以使用c3p0和阿里开发的druid 第三方包创建1个数据库连接池。

    其中c3p0会自动去加载配置文件,而druid使用工厂类获取数据库连接对象。

    1.c3p0创建数据库连接池

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
        <!--new ComboPooledDataSource("mvcApp");使用 -->
        <named-config name="mvcApp">
            <property name="user">weike</property>
            <property name="password">weike@123</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://192.168.0.98:3306/zhanggen?useUnicode=true&amp;serverTimezone=UTC&amp;characterEncoding=UTF-8</property>
            <!-- 以上的user是数据库的用户,
             password是数据库的密码,driverClass是mysql的数据库驱动,
             jdbcUrl是连接数据库的url -->
            <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
            <property name="acquireIncrement">5</property>
            <!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->
            <property name="initialPoolSize">10</property>
            <!--连接池中保留的最小连接数 -->
            <property name="minPoolSize">10</property>
            <!--连接池中保留的最大连接数-->
            <property name="maxPoolSize">10</property>
            <!--超时时间为3秒-->
            <property name="checkoutTimeout">3000</property>
            <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
            <property name="maxStatements">20</property>
            <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
            <property name="maxStatementsPerConnection">5</property>
        </named-config>
    </c3p0-config>
    c3p0-config.xml

    -----------------

    package com.mingde.c3p0;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    
    public class C3P0Demo1 {
        public static void main(String[] args) throws Exception {
            //1.创建数据库连接池对象,指定数据库配置mvcApp
            DataSource dataSource = new ComboPooledDataSource("mvcApp");
            //2.从连接池中获取连接对象
            for (int i = 0; i <= 10; i++) {
                Connection connection = dataSource.getConnection();
                System.out.println(connection);
            }
    
    
        }
    }
    C3P0Demo1.java

    2.druid创建数据库连接池

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://192.168.0.98:3306/zhanggen?serverTimezone=PRC
    username=weike
    password=weike@123
    #初始化连接数
    initialSize=10
    minIdle=5
    #最大连接数
    maxActive=10
    #最大等待时间
    maxWait=3000
    
    timeBetweenEvictionRunsMillis=6000
    minEvictableIdleTimeMillis=300000
    testWhileIdle=true
    testOnBorrow=true
    testOnReturn=true
    poolPreparedStatements=true
    maxPoolPreparedStatementPerConnectionSize=20
    validationQuery=select 1
    filters=stat
    druid.properties

    ----------------------

    package com.mingde.druid;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    import javax.sql.DataSource;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.util.Properties;
    
    public class DruidDemo1 {
        public static void main(String[] args)throws Exception {
            //加载配置文件
            Properties properties=new Properties();
            InputStream resourceAsStream = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(resourceAsStream);
            //创建连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            //通过工厂类获取连接对象
            for (int i = 0; i <11 ; i++) {
                Connection connection = dataSource.getConnection();
                System.out.println(connection);
            }
    
    
    
    
    
        }
    }
    DruidDemo1.java

    3. druid工具类

    package util;
    
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    import javax.sql.DataSource;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    public class DruidUtils {
        //1.定义成员变量
        private static DataSource dataSource;
    
        static {
            try {
                //2.加载配置文件
                Properties properties = new Properties();
                properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
                //3.创建Druid连接池
                dataSource = DruidDataSourceFactory.createDataSource(properties);
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        //获取数据库连接方法
        public static Connection getConnection() {
            Connection connection = null;
            try {
                connection = dataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
    
        //释放数据库连接资源方法 DML
        public static void Close(Statement statement, Connection connection) {
            try {
                if (statement != null) {
                    //归还数据库连接到数据库连接池
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        //释放数据库连接资源方法 DDL
        public static void Close(ResultSet resultSet, Statement statement, Connection connection) {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    //归还数据库连接到数据库连接池
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        //获取连接池
        public static DataSource getDataSource() {
            return dataSource;
        }
    }
    DruidUtils.java

    4.使用Junit包对druid工具类进行单元测试

    Junit单元测试,可以让类中的方法 在不依赖main方法的情况下独立执行。

    package com.mingde;
    
    
    import org.junit.Test;
    import util.DruidUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    public class TestUtilsDemo {
        @Test
        public void testInsert() throws Exception {
            //1.获取连接
            Connection connection = DruidUtils.getConnection();
            //2.定义SQL
            String insertSql = "insert into staffs (username,age,salary)  values (?,?,?)";
            //3.获取statement对象
            PreparedStatement preparedStatement = connection.prepareStatement(insertSql);
            //4.给?占位符赋值
            preparedStatement.setString(1, "卢俊义");
            preparedStatement.setInt(2, 68);
            preparedStatement.setDouble(3, 56.9);
            int count = preparedStatement.executeUpdate();
            System.out.println(count);
            //5.关闭数据库连接资源
            DruidUtils.Close(preparedStatement, connection);
        }
    
        @Test
        public void testQuery() throws Exception {
            //1.获取连接
            Connection connection = DruidUtils.getConnection();
            //2.定义SQL
            String querySql = "select id,username,age,salary from staffs where id = ?";
            //3.获取statement对象
            PreparedStatement preparedStatement = connection.prepareStatement(querySql);
            //4.把?占位符 赋值为45
            preparedStatement.setInt(1, 45);
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                //获取当前行的每个列
                int id = resultSet.getInt("id");
                String userName = resultSet.getString("username");
                int age = resultSet.getInt("age");
                double salary = resultSet.getDouble("salary");
                System.out.println(id + "----" + "----" + userName + "----" + age + "--------" + salary);
            }
            //5.关闭数据库连接资源
            DruidUtils.Close(resultSet, preparedStatement, connection);
        }
    
    }
    TestUtilsDemo.java

    5.使用druid之后产生大量超时连接

    mysql> show processlist;
    +------+-------+------------------+--------------+---------+-------+----------+------------------+
    | Id   | User  | Host             | db           | Command | Time  | State    | Info             |
    +------+-------+------------------+--------------+---------+-------+----------+------------------+
    |  473 | root  | 172.17.0.1:54128 | db_gjdw_eova | Sleep   |     1 |          | NULL             |
    |  604 | root  | 172.17.0.1:54420 | db_gjdw_eova | Sleep   |   912 |          | NULL             |
    |  606 | root  | 172.17.0.1:54424 | db_gjdw_data | Sleep   |   915 |          | NULL             |
    |  634 | root  | 172.17.0.1:54480 | db_gjdw_eova | Sleep   |   912 |          | NULL             |
    |  635 | root  | 172.17.0.1:54482 | db_gjdw_data | Sleep   |   596 |          | NULL             |
    |  636 | weike | 172.17.0.1:54484 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  637 | weike | 172.17.0.1:54486 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  638 | weike | 172.17.0.1:54488 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  639 | weike | 172.17.0.1:54490 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  640 | weike | 172.17.0.1:54492 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  641 | weike | 172.17.0.1:54494 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  642 | weike | 172.17.0.1:54496 | db_hbdw_data | Sleep   |  9278 |          | NULL             |
    |  643 | weike | 172.17.0.1:54498 | db_hbdw_data | Sleep   |  9276 |          | NULL             |
    |  644 | weike | 172.17.0.1:54500 | db_hbdw_data | Sleep   | 10605 |          | NULL             |
    |  645 | weike | 172.17.0.1:54502 | db_hbdw_data | Sleep   |   722 |          | NULL             |
    |  646 | weike | 172.17.0.1:54504 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  647 | weike | 172.17.0.1:54506 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  648 | weike | 172.17.0.1:54508 | db_hbdw_data | Sleep   | 20533 |          | NULL             |
    |  649 | weike | 172.17.0.1:54510 | db_hbdw_data | Sleep   |  3559 |          | NULL             |
    |  650 | weike | 172.17.0.1:54512 | db_hbdw_data | Sleep   |  4831 |          | NULL             |
    |  651 | weike | 172.17.0.1:54514 | db_hbdw_data | Sleep   | 20144 |          | NULL             |
    |  652 | weike | 172.17.0.1:54516 | db_hbdw_data | Sleep   |    67 |          | NULL             |
    |  653 | weike | 172.17.0.1:54518 | db_hbdw_data | Sleep   |    67 |          | NULL             |
    |  654 | weike | 172.17.0.1:54520 | db_hbdw_data | Sleep   | 20144 |          | NULL             |
    |  655 | weike | 172.17.0.1:54522 | db_hbdw_data | Sleep   |  5224 |          | NULL             |
    |  700 | weike | 172.17.0.1:54700 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  701 | weike | 172.17.0.1:54704 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  702 | weike | 172.17.0.1:54708 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  703 | weike | 172.17.0.1:54712 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  704 | weike | 172.17.0.1:54716 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  705 | weike | 172.17.0.1:54720 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  706 | weike | 172.17.0.1:54724 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  707 | weike | 172.17.0.1:54728 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  708 | weike | 172.17.0.1:54732 | rmyh         | Sleep   |  3502 |          | NULL             |
    |  709 | weike | 172.17.0.1:54736 | rmyh         | Sleep   |  3502 |          | NULL             |
    |  710 | weike | 172.17.0.1:54740 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  711 | weike | 172.17.0.1:54744 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  712 | weike | 172.17.0.1:54748 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  713 | weike | 172.17.0.1:54752 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  714 | weike | 172.17.0.1:54756 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  715 | weike | 172.17.0.1:54760 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  716 | weike | 172.17.0.1:54764 | rmyh         | Sleep   |  7666 |          | NULL             |
    |  717 | weike | 172.17.0.1:54768 | rmyh         | Sleep   |  7666 |          | NULL             |
    |  718 | weike | 172.17.0.1:54772 | rmyh         | Sleep   |  3502 |          | NULL             |
    |  719 | weike | 172.17.0.1:54776 | rmyh         | Sleep   |  3481 |          | NULL             |
    |  720 | weike | 172.17.0.1:54780 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  721 | weike | 172.17.0.1:54784 | rmyh         | Sleep   |  9553 |          | NULL             |
    |  722 | weike | 172.17.0.1:54788 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  723 | weike | 172.17.0.1:54792 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  724 | weike | 172.17.0.1:54796 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  725 | weike | 172.17.0.1:54800 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  726 | weike | 172.17.0.1:54804 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  727 | weike | 172.17.0.1:54808 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  728 | weike | 172.17.0.1:54812 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  729 | weike | 172.17.0.1:54816 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  730 | weike | 172.17.0.1:54820 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  731 | weike | 172.17.0.1:54824 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  732 | weike | 172.17.0.1:54828 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  733 | weike | 172.17.0.1:54832 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  734 | weike | 172.17.0.1:54836 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  735 | weike | 172.17.0.1:54840 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  736 | weike | 172.17.0.1:54844 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  737 | weike | 172.17.0.1:54848 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  738 | weike | 172.17.0.1:54852 | rmyh         | Sleep   |  9552 |          | NULL             |
    |  739 | weike | 172.17.0.1:54856 | rmyh         | Sleep   |  9552 |          | NULL             |
    | 1016 | root  | 172.17.0.1:55408 | db_gjdw_data | Sleep   |   917 |          | NULL             |
    | 1017 | root  | 172.17.0.1:55410 | db_gjdw_data | Sleep   |   911 |          | NULL             |
    | 1018 | root  | 172.17.0.1:55412 | db_gjdw_data | Sleep   |   911 |          | NULL             |
    | 1019 | root  | 172.17.0.1:55414 | db_gjdw_eova | Sleep   |   911 |          | NULL             |
    | 1043 | root  | 172.17.0.1:55462 | db_gjdw_eova | Sleep   |   912 |          | NULL             |
    | 1044 | root  | 172.17.0.1:55464 | db_gjdw_data | Sleep   |   911 |          | NULL             |
    | 1045 | root  | 172.17.0.1:55466 | db_gjdw_eova | Sleep   |   911 |          | NULL             |
    | 1046 | root  | 172.17.0.1:55468 | db_gjdw_data | Sleep   |   917 |          | NULL             |
    | 1047 | root  | 172.17.0.1:55470 | db_gjdw_data | Sleep   |   911 |          | NULL             |
    | 1048 | root  | 172.17.0.1:55472 | db_gjdw_data | Sleep   |   911 |          | NULL             |
    | 1055 | weike | 172.17.0.1:55486 | zhanggen     | Sleep   |   765 |          | NULL             |
    | 1056 | weike | 172.17.0.1:55488 | zhanggen     | Sleep   |   765 |          | NULL             |
    | 1088 | root  | localhost        | NULL         | Query   |     0 | starting | show processlist |
    +------+-------+------------------+--------------+---------+-------+----------+------------------+
    78 rows in set (0.00 sec)
    mysql> show processlist;

    我修改了数据库配置文件在MySQL server端对连接超时时间进行了限制。

    [mysqld]
    user=mysql
    character-set-server=utf8
    skip-name-resolve
    #连接超时时间
    wait_timeout=10
    #普通SQL执行日志 
    general_log=ON
    general_log_file=/var/log/docker/query.log 
    #慢日志执行日志
    slow_query_log=ON 
    slow_query_log=5 
    slow_query_log_file=/var/log/docker/slow-query.log
    default_authentication_plugin=mysql_native_password
    sql_mode =STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8
    my.cnf

    四、JdbcTemplate

    JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。

    jdbc Template是建立在1个数据库连接池之上的。

    JdbcTemplate是Spring的一部分。JdbcTemplate处理了资源的建立和释放。他帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。

    1.JdbcTemplate 快速入门

    package com.zhanggen;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    import util.DruidUtils;
    import util.JDBCUtils;
    
    public class jdbcTemplateDemo1 {
        public static void main(String[] args) {
            //1.创建JDBCTemplate对象,需要1个依赖1个数据库连接池 参数
            JdbcTemplate template=new JdbcTemplate(DruidUtils.getDataSource());
            //2.调用方法
            String sql="update staffs set username = ? where id = ?";
            int count = template.update(sql, "武松", 46);
            System.out.println(count);
    
        }
    }

    2.JdbcTemplate 执行DML语句

     使用Jdbc Template执行增、删、修改操作。

    package com.zhanggen;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.jdbc.core.JdbcTemplate;
    import util.DruidUtils;
    
    public class JdbcTemplateDemo2 {
    
        private static JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        private static String preparedSQL = null;
    
        public static void indertEntry() throws Exception {
            preparedSQL = "update (taffs set age=? where username=?";
            template.update(preparedSQL, 89, "武松");
        }
    
        public static void addStaff() {
            preparedSQL = "insert into staffs (username,age,salary) values (?,?,?)";
            template.update(preparedSQL, "张无忌", 30, 98.98);
        }
    
        public static void deleteStaff() {
            preparedSQL = "delete from staffs where username=?";
            template.update(preparedSQL, "藤田刚");
        }
    
    }

    2.JdbcTemplate 执行DQL语句

    使用Jdbc Template执行数据库查询操作,并把查询结果封装成对象,添加到List中。

    package com.zhanggen;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.jdbc.core.BeanPropertyRowMapper;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowMapper;
    import util.DruidUtils;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.List;
    import java.util.Map;
    
    public class JdbcTemplateDemo2 {
    
        private static JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        private static String preparedSQL = null;
    
        //1.JdbcTemplate执行DML操作
        public static void indertEntry() throws Exception {
            preparedSQL = "update (taffs set age=? where username=?";
            template.update(preparedSQL, 89, "武松");
        }
    
        public static void addStaff() {
            preparedSQL = "insert into staffs (username,age,salary) values (?,?,?)";
            template.update(preparedSQL, "张无忌", 30, 98.98);
        }
    
        public static void deleteStaff() {
            preparedSQL = "delete from staffs where username=?";
            template.update(preparedSQL, "藤田刚");
        }
    
        //2.JdbcTemplate执行DQL操作
        public static void queryForMap() {
            //查询结果封装为map类型
            preparedSQL = "select username,age,salary from staffs where id = ?";
            Map<String, Object> map = template.queryForMap(preparedSQL, 44);
            System.out.println(map);
    
        }
    
        public static void queryForList() {
            //查询结果封装为List类型
            preparedSQL = "select * from staffs";
            List<Map<String, Object>> list = template.queryForList(preparedSQL);
            System.out.println(list);
    
        }
    
        public static void query1() {
            //查询staffs表中所有记录,把每一条记录封装为staff对象,并添加到集合中。
            preparedSQL = "select * from staffs";
            List<Staff> staffList = template.query(preparedSQL, new RowMapper<Staff>() {
                @Override
                public Staff mapRow(ResultSet resultSet, int i) throws SQLException {
                    Staff staff = new Staff();
                    int id = resultSet.getInt("id");
                    String username = resultSet.getString("username");
                    int age = resultSet.getInt("age");
                    double salary = resultSet.getDouble("salary");
                    staff.setId(id);
                    staff.setUsername(username);
                    staff.setAge(age);
                    staff.setSalary(salary);
                    return staff;
                }
            });
            System.out.println(staffList);
        }
    
        public static void query2() {
            //简化版
            //查询staffs表中所有记录,把每一条记录自动封装为staff对象,并添加到集合中。
            preparedSQL = "select * from staffs";
            List<Staff> staffList = template.query(preparedSQL, new BeanPropertyRowMapper<Staff>(Staff.class));
            System.out.println(staffList);
        }
    
        //3.用于做SQL聚合函数的查询
        public static void queryForObject() {
            preparedSQL = "select count(id) from staffs";
            Long total = template.queryForObject(preparedSQL, Long.class);
            System.out.println(total);
        }
    
    
    }

     

    五、DAO层概念

    ORM可以帮助我们把数据中表映射为class类,把每表中的每条记录映射为object对象,使我们可以通过代码操作数据库,在这个基础之上我们还可以进一步对操作数据库的代码进行封装,那就是使用DAO层。

    在Java中我们可以使用DAO类对JDB操作表的细节进行代码封装;

    DAO(Database Access Object)是指可以提供数据库访问对象的类

    作用:数据库访问对象(DAO)在开发时提供针对某1张表的增删改查操作细节;

    优势:DAO可以提高代码封装性,通过数据库访问对象可以避免反复书写SQL以及JDBC开发步骤的书写;

    开发规则:

    1个DAO类中封装1张表的封装细节;

    DAO类命名规则:表名+Dao,比如对employee表的增删改查操作细节进行封装,此时的DAO就应该命名为EmployeeDAO;

    DAO类所在包的命名规则:公司网站的域名.dao,例如com.le.dao;

    参考

  • 相关阅读:
    Nodejs下载和第一个Nodejs示例
    永久关闭Win10工具栏的TaskbarSearch控件
    对称加密,非对称加密,散列算法,签名算法
    【转】TTL和RS232之间的详细对比
    zlg核心板linux系统中查看系统内存等使用信息
    Power BI后台自动刷新数据报错 The operation was throttled by Power BI Premium because there were too many datasets being processed concurrently.
    剪切板和上传文件内容获取
    CSS, LESS, SCSS, SASS总结
    文字程序
    electron 打包“ERR_ELECTRON_BUILDER_CANNOT_EXECUTE”
  • 原文地址:https://www.cnblogs.com/sss4/p/15641832.html
Copyright © 2011-2022 走看看