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); //当某个线程使用完数据库链接之后,归还回去
}
}