sss4

前言

在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;

 

 

 

 

参考

分类:

技术点:

相关文章: