JDBC

基本使用步骤

  1. 在官网下载对应的jar包并导入项目

  2. 加载驱动

    Class.forName(“com.mysql.jdbc.Driver);

  3. 创建一个链接

    Connection conn = DriverManager.getConnection(“url”,”user”,”password”);

  4. 执行完所有语句后关闭连接

    conn.close();

package hellojdbc;

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

/**
 * 1. 导入jar包
 * 2. 注册驱动
 * 3. 创建数据库连接
 */
public class JDBCConnDemo {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");

            /**
             * 不这样写的原因:
             * 1. 会导致注册两次
             * 2. 会时程序依赖于MySQL数据包
             */
            //DriverManager.registerDriver(new Driver());//第二种注册方式

            //使用DriverManager获取一个数据库连接
            conn = DriverManager.getConnection(
                    //指定数据库类型,所在URL,所用数据库,用户名及密码
                    "jdbc:mysql://127.0.0.1:3306/blog?useSSL=false"
                    ,"root","xxxxxx");
            //进行增删查改操作
            System.out.println("连接成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //释放资源
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("关闭成功");
    }
}

执行SQL语句

查询语句

package hellojdbc;

import java.sql.*;

public class JDBCDemo2 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1:3306/blog?useSSL=false",
                    "root",
                    "xxx"
            );
            //使用connection创建一个Statement对象(执行SQL语句的工具接口)
            statement = connection.createStatement();

            /**
             * statement执行SQL语句的方法:
             * 1. execute()可以执行任何SQL语句,返回boolean值
             *    执行后第一个结果是ResultSet,否则返回true
             * 2. executeQuery()执行select()语句,返回查询到的结果集
             * 3. executeUpdate()执行DML(insert,update,delete)语句,返回影响的记录条数
             */
            resultSet = statement.executeQuery("select * from categories");
            //获取结果
            while (resultSet.next()){
                //根据第几列获取值
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                //根据字段名获取值
                int pid = resultSet.getInt("pid");
                String path = resultSet.getString("path");
                System.out.println(id+" "+name+" "+pid+" "+path);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            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();
                }
            }
        }
    }
}

DML语句

package hellojdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo3 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1:3306/blog?useSSL=false",
                    "root",
                    "xxxxxx"
            );
            statement = connection.createStatement();
            //返回执行受影响的条数,执行失败返回0
            int i = statement.executeUpdate(
                    "update categories set path='改一下试试' where id=1"
            );
            if(i>0){
                System.out.println("更新成功");
            }else{
                System.out.println("更新失败");
            }

            int j = statement.executeUpdate(
                    "insert into categories(name,pid,path) values ('插入语句',2,'要用单引号');"
            );
            if(j>0){
                System.out.println("插入成功");
            }else{
                System.out.println("插入失败");
            }

            int k = statement.executeUpdate(
                    "delete from categories where id = 2;"
            );
            if(k>0){
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 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();
            }
        }
    }
}

使用PreparedStatement防止SQL注入

package hellojdbc;

import java.sql.*;

public class JDBCDemo4 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1/blog?useSSL=false",
                    "root",
                    "xxx"
            );
            //使用?占位符,执行时会替换成实际数据,预编译
            preparedStatement = connection.prepareStatement("select * from students where score != ?");
            //给preparedStatement设置参数,第一个参数是索引从1开始,第二个是具体值
            preparedStatement.setInt(1,0);
            //执行
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){
                System.out.println(resultSet.getString(1)+"\t"
                    +resultSet.getInt(2)+"\t"
                    +resultSet.getString(3)+"\t"
                    +resultSet.getInt(4));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

批量插入

package hellojdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;

public class JDBCDemo5 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        Random r = new Random();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1/blog?useSSL=false",
                    "root",
                    "xxx");
            statement = connection.createStatement();//每次都要写语句,无法避免SQL注入
            //设置事务不自动提交
            connection.setAutoCommit(false);
            for (int i = 0; i < 10000; i++) {
                //添加到缓存区
                statement.addBatch("insert into students(stuName,age,course,score) " +
                        "values ('测试" + i + "'," + r.nextInt(30) + ",'语数英'," + r.nextInt(100) + ")");
                if (i % 50 == 0) {
                    //执行批处理
                    int[] ints = statement.executeBatch();
                    System.out.println(ints.length);
                    statement.clearBatch();//清理缓存区
                }
            }
            //手动提交事务
            statement.executeBatch();
            connection.commit();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            try {
                connection.rollback();//出错回滚
                connection.commit();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            if(statement!= null){
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

可以使用prepareStatement避免SQL注入

prepareStatement ps = connection.prepareStatement("insert into students(name,age) values (?,?)");
for (int i=0;i<100;i++){
    ps.setString(1,"xxx");
    ps.setInt(2,1);
    //放入批处理
    ps.addBatch();

    int[] rs = ps.executeBatch();
    ps.clearBatch();
}

读取和写入二进制文件

package hellojdbc;

import java.io.*;
import java.sql.*;

public class JDBCDemo6 {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement1 = null;
        PreparedStatement preparedStatement2 = null;
        PreparedStatement preparedStatement3 = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1/blog?useSSL=false",
                    "root",
                    "zm19980225"
            );
            String sql1 = "drop table if exists xmlTables";
            String sql2 = "create table xmlTables(" +
                    "id int primary key auto_increment," +
                    "data text)";
            preparedStatement1 = connection.prepareStatement(sql1);
            //执行sql1
            preparedStatement1.execute();
            //执行sql2
            preparedStatement1.execute(sql2);

            //添加数据
            preparedStatement2 = connection.prepareStatement("insert into xmlTables(data) values (?)");
            File file = new File("src/hellojdbc/emp.xml");
            InputStream in = new FileInputStream(file);
            //此处有三种方法:
            //preparedStatement2.setAsciiStream(1,in,file.length());
            //preparedStatement2.setCharacterStream(1,new InputStreamReader(in),file.length());
            preparedStatement2.setBinaryStream(1,in,file.length());
            int i = preparedStatement2.executeUpdate();
            if(i>0){
                System.out.println("添加成功");
            }
            //读取数据
            preparedStatement3 = connection.prepareStatement("select * from xmlTables where id=?");
            preparedStatement3.setInt(1,1);
            ResultSet resultSet = preparedStatement3.executeQuery();
            if(resultSet.next()){
                int id = resultSet.getInt("id");
                InputStream data = resultSet.getBinaryStream("data");
                System.out.println("id:"+id);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] bytes = new byte[1024];
                int curr = -1;
                while((curr = data.read(bytes))!=-1){
                    baos.write(bytes,0,curr);
                }
                System.out.println("data:"+baos.toString());
                baos.close();
                data.close();
            }
            in.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                preparedStatement3.close();
                preparedStatement2.close();
                preparedStatement1.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

设置隔离级别和保存点

//设置隔离即便
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

//保存点,回滚的时候指定只回滚到指定位置
SavaPoint savepoint = connection.setSavepoint("save1");//上面的语句不会回滚
connection.rollback(savepoint);

数据库连接池

创建一个连接池,每次需要的的时候从连接池获取连接,减少每次用户都要从服务器获取连接,效率低
使用DataSource接口

package hellojdbc;

import hellojdbc.com.xm.util.DbUtiles;

import javax.sql.DataSource;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.logging.Logger;

public class MyJDBCPool implements DataSource {
    //实现线程同步控制
    private static List<Connection> list = Collections.synchronizedList(new LinkedList<>());
    static {
        try {
            Properties properties = new Properties();
            InputStream is = DbUtiles.class.getClassLoader().getResourceAsStream("database.properties");
            properties.load(is);
            is.close();
            String driver = properties.getProperty("driver");
            String url = properties.getProperty("url");
            String usename = properties.getProperty("user");
            String password = properties.getProperty("password");
            Class.forName(driver);
            for(int i=0;i<5;i++){
                Connection connection = DriverManager.getConnection(url,usename,password);
                list.add(connection);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        if(list.size()>0){
            Connection connection = list.remove(0);
            System.out.println("还剩"+list.size()+"个");
            return connection;
        }
        return null;
    }

    /**
     * 用完释放放回
     * @param connection
     */
    public void release(Connection connection){
        list.add(connection);
        System.out.println("放回成功");
    }
    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public ConnectionBuilder createConnectionBuilder() throws SQLException {
        return null;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public ShardingKeyBuilder createShardingKeyBuilder() throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

public class PoolTest {
    public static void main(String[] args) {
        MyJDBCPool pool = new MyJDBCPool();
        for(int i=0;i<5;i++){
            try {
                Connection connection = pool.getConnection();
                System.out.println("使用:"+connection.hashCode());
                pool.release(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

DBCP连接池

需要下载三个包:

  • commons-dbcp.jar
  • commons-pool.jar
  • commons-logging.jar

配置文件

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/blog?useSSL=false
username = root
password = xxx

#初始化连接
initialSize = 5

#最大连接数量
maxActive = 10

#最大空闲数量
maxIdle = 6

#最小空闲数量
minIdle = 2

#超时等待时间,以毫秒为单位
maxWaitMillis = 60000
package hellojdbc;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

public class DBCPTest {
    public static void main(String[] args) {
        try {
            BasicDataSourceFactory factory = new BasicDataSourceFactory();
            Properties properties = new Properties();
            InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            properties.load(is);
            BasicDataSource pool = factory.createDataSource(properties);

            for (int i = 0; i < 50; i++) {
                Connection conn = pool.getConnection();
                System.out.println(conn);
                conn.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

C3P0连接池

需要下载c3p0-0.9.5.2.bin,导入两个包

  • c3p0.jar
  • mchange-commons-java.jar

配置文件

<c3p0-config>
    <!-- 默认配置,如果没有指定则使用这个配置 -->
    <default-config>
        <!-- 基本配置 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/blog?useSSL=false</property>
        <property name="user">root</property>
        <property name="password">zm19980225</property>
        <!--扩展配置 -->
        <!-- 连接超过30秒报错 -->
        <property name="checkoutTimeout">30000</property>
        <!-- 30秒检查空闲连接 -->
        <property name="idleConnectionTestPeriod">30</property>
        <!-- 初始化池大小 -->
        <property name="initialPoolSize">2</property>
        <!-- 最大空闲时间 -->
        <property name="maxIdleTime">30</property>
        <!-- 最多有多少个连接 -->
        <property name="maxPoolSize">10</property>
        <!-- 最少几个连接 -->
        <property name="minPoolSize">2</property>
        <!-- 每次最多可以执行多少个批处理语句 -->
        <property name="maxStatements">50</property>
    </default-config>
    <!-- 命名的配置 -->
    <named-config name="xiaoming">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/blog?useSSL=false</property>
        <property name="user">root</property>
        <property name="password">zm19980225</property>
        <!-- 如果池中数据连接不够时一次增长多少个 -->
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">100</property>
        <property name="minPoolSize">50</property>
        <property name="maxPoolSize">1000</property>
        <property name="maxStatements">0</property>
        <property name="maxStatementsPerConnection">5</property>
    </named-config>
</c3p0-config>
package hellojdbc;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class C3P0Test {
    public static void main(String[] args) {
        //创建连接,指定所用配置,文件命名使用“c3p0-config.xml"或者"c3p0-config.properties",默认路径在rc目录下
        ComboPooledDataSource pool = new ComboPooledDataSource("xiaoming");
        //使用
        for (int i = 0; i < 30; i++) {
            try {
                Connection conn = pool.getConnection();
                System.out.println(conn.getClass());
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

阿里Druid连接池

官方文档

url = jdbc:mysql://127.0.0.1:3306/blog?useSSL=false
username = root
password = zm19980225
driverClassName = com.mysql.jdbc.Driver
# 初始化连接池大小
initialSize = 10
# 最大连接池数
maxActive = 20
# 最小链接池数
minIdle = 5
# 获取连接时最大等待时间,单位毫秒
maxWait = 30000
package hellojdbc;

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

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

public class DruidTest {
    public static void main(String[] args) {
        //创建连接池
        DruidDataSource dataSource = null;
        try {
            Properties properties = new Properties();
            InputStream is = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(is);
            is.close();
            //druid数据源工厂
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 30; i++) {
            try {
                Connection conn = dataSource.getConnection();
                System.out.println(conn.getClass().getName());
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

Apache封装的DbUtiles用法

package DBUtilsTest;

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

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

public class DruidUtiles {
    private static DruidDataSource dataSource;
    static {
        try {
            //1.加载集合
            Properties properties = new Properties();
            InputStream is = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(is);
            is.close();
            dataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static DataSource getDataSource(){
        return dataSource;
    }
}

package DBUtilsTest;

import com.xm.beans.Student;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class DBUtilesDemo {
    public static void main(String[] args) {
        //创建QueryRunner
        QueryRunner queryRunner = new QueryRunner(DruidUtiles.getDataSource());

        try {
            //查询一条语句变成一个数组
            Object[] objects = queryRunner.query("select * from students where id=1",new ArrayHandler());
            for (Object o : objects) {
                System.out.println(o);
            }

            //查询多条数据
            List<Object[]> objects1 = queryRunner.query("select * from students", new ArrayListHandler());
            for (Object[] o : objects1) {
                System.out.println(o);
            }

            //查询数据的某一列
            List<String> stuName = queryRunner.query("select * from students", new ColumnListHandler<String>("stuName"));
            for (String s : stuName) {
                System.out.println(s);
            }

            //查询一条数据,把输出放入Map集合,key存属性,value存数据
            Map<String,Object> map = queryRunner.query("select * from students where id=1",new MapHandler());
            for (Map.Entry<String,Object> entry:map.entrySet()) {
                System.out.println(entry.getKey()+"=>"+entry.getValue());
            }

            //查询数据个数
            Long total = queryRunner.query("select count(*) from students",new ScalarHandler<Long>());
            System.out.println(total);

            //查询一条记录,把它封装成对象
            Student student = queryRunner.query("select * from students where id=1",new BeanHandler<Student>(Student.class));
            System.out.println(student.toString());

            //查询全部数据并封装成对象放入集合
            List<Student> students = queryRunner.query("select * from students",new BeanListHandler<Student>(Student.class));
            for (Student student1 : students) {
                System.out.println(student1.toString());
            }

            //执行删除语句
            int result  = queryRunner.update("delete from students where id=?",10);
            System.out.println(result);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}