MySQL 从入门到入魔之数据库连接池 (04)
- 2021 年 12 月 23 日
本文字数:4991 字
阅读完需:约 16 分钟
数据库连接池
为什么使用数据库连接池?如果不使用连接池每一次客户端发出的业务请求都需要对应一次数据库连接,如果有一万次请求就有一万次数据库连接的建立和断开,频繁的开关连接会影响程序的执行效率,通过数据库连接池可以将数据库连接进行复用,从而提高执行效率.
如何使用?
jdbc.properties
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/newdb3?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
db.username=root
db.password=123456
db.maxActive=10
db.initialSize=2
读取*.properties 配置文件
//创建读取配置文件的属性对象
Properties p = new Properties();
//得到文件输入流 这种写法会自动去src/main/resources目录下找文件
InputStream ips = Demo03.class.getClassLoader()
.getResourceAsStream("my.properties");
//把文件输入流交给属性对象
p.load(ips);
//读取数据
String name = p.getProperty("name");
//getProperty方法只能读取字符串
String age = p.getProperty("age");
System.out.println(name+":"+age);
读取 jdbc.properties 配置文件
public class DBUtils {
private static DruidDataSource ds;
//因为读取配置文件只需要读取一次,连接池对象也只需要创建一次
static {
//读取配置文件里面的数据
Properties p = new Properties();
InputStream ips = DBUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
p.load(ips);
} catch (IOException e) {
e.printStackTrace();
}
String driver = p.getProperty("db.driver");
String url = p.getProperty("db.url");
String username = p.getProperty("db.username");
String password = p.getProperty("db.password");
String maxActive = p.getProperty("db.maxActive");
String initialSize = p.getProperty("db.initialSize");
ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
// 设置初始连接数量
ds.setInitialSize(Integer.parseInt(initialSize));
// 设置最大连接数量
ds.setMaxActive(Integer.parseInt(maxActive));
}
public static Connection getConn() throws SQLException {
// 注册驱动
// 从连接池对象中获取连接 异常抛出
Connection conn = ds.getConnection();
System.out.println(conn);
return conn;
}
}
创建用户表 use newdb3;create table user(id int primary key auto_increment,username varchar(20),password varchar(20))charset=utf8;
注册功能
import java.sql.Connection;
import java.sql.Statement;
import java.util.Scanner;
/**
* 注册功能
* @author 海拥😋
* @date 2021年12月23日 下午2:04:42
*/
public class Demo04 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
sc.close();
// 获取连接
try (Connection conn = DBUtils.getConn();) {
Statement s = conn.createStatement();
String sql = "insert into user values(null,'"+username+"','"+password+"')";
s.executeUpdate(sql);
System.out.println("注册成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
登录功能
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
/**
* 登录功能
* @author 海拥😋
* @date 2021年12月23日 下午2:11:29
*/
public class Demo05 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//获取连接
try (Connection conn = DBUtils.getConn();) {
Statement s = conn.createStatement();
// String sql =
// "select count(*) from user where username='"
// +username+"'and password='"+password+"'";
// ResultSet rs = s.executeQuery(sql);
//通过PrepredStatement解决SQL注入问题
String sql = "select count(*) from user where username=? and password=?";
//在编译时已经将SQL语句的业务逻辑锁死 用户写的内容不会再影响逻辑
PreparedStatement ps = conn.prepareStatement(sql);
//替换sql中的?
ps.setString(1, username);
ps.setString(2, password);
//执行SQL
ResultSet rs = ps.executeQuery();
//查询回来的是符合条件的数量 只有一条数据所以可以用if 如果查询回来的是
//多条数据必须用while
if(rs.next()) {
//取出查询回来的符合条件的数量
int count =rs.getInt(1);
if(count>0) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Statement 和 PreparedStatement
如果执行的 SQL 语句中存在变量,为了避免 SQL 注入所以使用 PreparedStatement
如果 SQL 语句中没有变量则使用 Statement
批量操作
批量操作就是将多条 SQL 语句执行时的多次网络数据传输合并成一次传输,从而提高执行效率
代码参考 Demo06.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
/**
* 批量操作
* @author 海拥😋
* @date 2021年12月23日 下午3:27:24
*/
public class Demo06 {
public static void main(String[] args) {
//获取连接
try (Connection conn = DBUtils.getConn();) {
String sql1="insert into user values(null,'刘备','123')";
String sql2="insert into user values(null,'关羽','123')";
String sql3="insert into user values(null,'张飞','123')";
Statement s = conn.createStatement();
// s.executeUpdate(sql1);
// s.executeUpdate(sql2);
// s.executeUpdate(sql3);
//通过批量操作将多次数据传输合并成一次
// s.addBatch(sql1);
// s.addBatch(sql2);
// s.addBatch(sql3);
// //执行批量操作
// s.executeBatch();
// System.out.println("执行完成");
//preparedStatement批量操作
String sql = "insert into user values(null,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0;i<100;i++) {
ps.setString(1, "name"+i);
ps.setString(2, "pw"+i);
//添加到批量操作
ps.addBatch();
//每隔20次执行一次 避免内存溢出
if(i%20==0) {
ps.executeBatch();
}
}
//执行批量操作
ps.executeBatch();
System.out.println("执行完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
分页查询
代码参考 Demo07.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;
/**
* 分页查询
* @author 海拥😋
* @date 2021年12月23日 下午4:22:49
*/
public class Demo07 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入查询的页数");
int page = sc.nextInt() ;
System.out.println("请输入查询的条数");
int count = sc.nextInt();
if(page<1) {
System.out.println("输入错误");
}
//获取连接
try (Connection conn = DBUtils.getConn();) {
String sql ="select username,password from user limit ?,?";
PreparedStatement ps =conn.prepareStatement(sql);
//第一个?代表跳过的条数=(请求页数-1)*条数
ps.setInt(1, (page-1)*count);
//第二个?代表请求条数(每页条数)
ps.setInt(2,count);
//执行查询
ResultSet rs = ps.executeQuery();
while(rs .next()) {
String username = rs.getString(1);
String password = rs.getString(2);
System.out.println( username+":"+password) ;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
获取自增主键值
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* 获取自增主键值
* @author 海拥😋
* @date 2021年12月23日 下午4:40:33
*/
public class Demo08 {
public static void main(String[] args) {
//获取连接
try (Connection conn = DBUtils.getConn();) {
String sql =
"insert into user values(null,'james','123456')";
Statement s = conn.createStatement();
//编译SQL语句时,需要设置返回自增主键值
s.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
//通过结果集 获取自增的主键值
ResultSet rs = s.getGeneratedKeys();
if(rs.next()) {
int id =rs.getInt(1);
System.out.println("id="+id);
}
System.out.println("插入完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
创建球队表 create table team(id int primary key auto_increment,name varchar(10))charset=utf8;
创建球员表 create table player(id int primary key auto_increment,name varchar(10),teamId int)charset=utf8;
球队球员小练习
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
/**
* @author 海拥😋
* @date 2021年12月23日 下午5:17:59
*/
public class Demo09 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入球队名字");
String teamName = sc.nextLine();
System.out.println("请输入球员名字");
String playerName = sc.nextLine();
// 获取连接
try (Connection conn = DBUtils.getConn();) {
String sql = "insert into team values(null,?)";
PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
// 替换?
ps.setString(1, teamName);
// 执行
ps.executeUpdate();
// 获取自增主键值
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
int teamId = rs.getInt(1);
System.out.println("球队id:"+teamId);
String psql = "insert into player values(null,?,?)";
PreparedStatement pps = conn.prepareStatement(psql);
pps.setString(1, playerName);
pps.setInt(2, teamId);
pps.executeUpdate();
System.out.println("保存完成!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码介绍
Demo04 注册功能
Demo05 登录功能 接触了预编译的 Sql 执行对象 讲解了 SQL 注入(给用户写值的位置,用户写进去了 SQL 语句 导致原有逻辑发生改变)
Demo06 批量操作
Demo07 分页查询
Demo08 获取自增主键值
Demo09 球队球员小练习
版权声明: 本文为 InfoQ 作者【海拥(haiyong.site)】的原创文章。
原文链接:【http://xie.infoq.cn/article/cb877f858b1d1ca82c2de9709】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
公众号:海拥 2021.11.29 加入
【个人网站】haiyong.site 【软件技能】Java,Python,JS 【兴趣爱好】学习使我快乐,编程令我永生 【个人称号】HDZ核心组成员,CSDN原力作者
评论