Loading

JDBC与数据库连接池

JDBC

1.导入相关包,建立数据库链接:

package jdbc;

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

public class TestJDBC {
    public static void main(String[] args) {
            // 建立与数据库的Connection连接
            // 这里需要提供:
            // 数据库所处于的ip:127.0.0.1 (本机)
            // 数据库的端口号: 3306 (mysql专用端口号)
            // 数据库名称 travel
            // 编码方式 UTF-8
            // 账号 root
            // 密码 123
            Connection c = DriverManager
                    .getConnection(
                            "jdbc:mysql://127.0.0.1:3306/travel?characterEncoding=UTF-8",
                            "root", "123");
            System.out.println("连接成功,获取连接对象: " + c);
        }  catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

2.常用Statement、PreparedStatement进行SQL操作:

package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) {
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/travel?characterEncoding=UTF-8","root", "123");
            Statement s = c.createStatement();
            PreparedStatement ps = c.prepareStatement(sql);
        ) {
            // Statement需要进行字符串拼接,可读性和维修性比较差
            String sql0 = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
            s.execute(sql0);

            // PreparedStatement 使用参数设置,可读性好,不易犯错,并可以防止SQL注入
            // "insert into hero values(null,?,?,?)";
            ps.setString(1, "提莫");
            ps.setFloat(2, 313.0f);
            ps.setInt(3, 50);
            ps.execute();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.execute与executeUpdate的区别:
相同点:execute与executeUpdate都可以执行增加,删除,修改
不同点1:
execute可以执行查询语句
然后通过getResultSet,把结果集取出来
executeUpdate不能执行查询语句
不同点2:
execute返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等
executeUpdate返回的是int,表示有多少条数据受到了影响

package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) {
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            Statement s = c.createStatement();) {
            // 不同1:execute可以执行查询语句
            // 然后通过getResultSet,把结果集取出来
            String sqlSelect = "select * from hero";
            s.execute(sqlSelect);
            ResultSet rs = s.getResultSet();
            while (rs.next()) {
                System.out.println(rs.getInt("id"));
            }
            // executeUpdate不能执行查询语句
            // s.executeUpdate(sqlSelect);
            // 不同2:
            // execute返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等
            boolean isSelect = s.execute(sqlSelect);
            System.out.println(isSelect);
            // executeUpdate返回的是int,表示有多少条数据受到了影响
            String sqlUpdate = "update Hero set hp = 300 where id < 100";
            int number = s.executeUpdate(sqlUpdate);
            System.out.println(number);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

4.开始事务处理:

package JDBC;
import java.sql.*;

public class Transaction {
    public static void main(String[] args) {
        System.out.println("尝试连接MySQL....");

        String sql = "select * from user where id< ? and name like ?";
        try(
                Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/travel?characterEncoding=UTF-8","root","kunkun0509");
                // 根据sql语句创建PreparedStatement
                PreparedStatement ps = c.prepareStatement(sql);   //防止SQL注入
                Statement s = c.createStatement();
        ) {
            c.setAutoCommit(false);  //开启事务测试
            ps.setInt(1,10);
            ps.setString(2,"%小芳%");

            sql = "update user set name='小明2019' where name='小明'";
            s.execute(sql);

            sql = "updata user set name='小明2019' where name='小明'";   //错误SQL语句
            s.execute(sql);
            //手动提交,只有当前所有执行成功的时候才会生效,因此第一个更新操作也不会成功
            c.commit();
            ps.setInt(1, 10);
            ps.setString(2, "%小芳%");
            ResultSet rs = ps.executeQuery(sql);
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String sex = rs.getString("sex");
                int age = rs.getInt("age");
                System.out.println("用户信息:" + " id ="+ id + ",用户名:"+name+",性别:"+sex+",年龄:"+age);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

5.ORM与DAO的概念和简单理解:
6.数据库线程池的简单使用:

package JDBC;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

// 数据库连接池还可以进一步用单例优化,避免多次实例化建立过多的链接
public class ConnectionPool {
    private static List<Connection> cs = new ArrayList<>();
    private static final int MAX_SIZE = 10;  //规定最大线程数

    //创建一个私有对象(单例模式)
    private static ConnectionPool instance = null;

    //将构造函数设为private型 防止外部实例化对象(通过反射或反序列化可以破解单例)
    private ConnectionPool(){};

    //判断ConnectionPool实例化的对象是否存在,不存在就实例化一个
    public static ConnectionPool getInstance() {
        if(instance == null) {
            synchronized (ConnectionPool.class) {
                if(instance == null) {
                    instance = new ConnectionPool();
                    instance.init(MAX_SIZE);
                }
            }
        }
        return instance;
    }

//    public ConnectionPool(int size) throws Exception {
//        if(size > MAX_SIZE) {
//            throw new Exception("线程池过大!不能超过"+MAX_SIZE+"个数据库链接池");
//        }
//        this.size = size;
//        init();
//    }

    private void init(int size) {
        try {
            for (int i = 0; i < size; i++ ) {
                Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/travel?characterEncoding=UTF-8","root","kunkun0509");
                cs.add(c);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public synchronized Connection getContection() {
        while (cs.isEmpty()) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Connection c = cs.remove(0);
        return c;
    }

    public synchronized void returnContection(Connection c) {
        cs.add(c);
        this.notifyAll();
    }
}

package JDBC;

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

public class TestConnectionPool {
    public static void main(String[] args) {
        //初始化数据库线程池
        ConnectionPool cp = ConnectionPool.getInstance();

        //线程池设置了单例模式之后,就不用担心过多实例化导致数据链接超过限定
//        for (int i = 0 ; i < 10000 ; i++) {
//            cp = new ConnectionPool();
//        }
        for (int i = 0; i < 100; i++ ) {
            new WorkingThread("WorkingThread " + i , cp).start();
        }

    }

}

class WorkingThread extends Thread {
    private ConnectionPool cp;

    public WorkingThread(String name,ConnectionPool cp) {
        super(name);
        this.cp = cp;
    }

    public void run() {
        Connection c = cp.getContection();
        System.out.println(this.getName()+" 获取了一个数据库链接,并开始工作");
        try(Statement st = c.createStatement()) {
            //模拟时间1s
            Thread.sleep(1000);
            st.execute("select * from user");
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        cp.returnContection(c);   //当某个线程使用完数据库链接之后,归还回去
    }
}

posted @ 2020-04-03 16:18  集君  阅读(27)  评论(0编辑  收藏  举报