如何通过Java操作数据库。 JDBC,全程是 Java Database Connectivity
- 在Java中用来规范如何访问关系型数据库,由各大数据库厂商去实现它
- 属于JaveSE的一部分
JDBC使用步骤
- 将Driver(驱动程序)注册到DriverManager(驱动程序管理者)
- 利用DriverManager创建Connection(数据库连接)
- 利用Connection创建Statement(语句)
- 利用Statement执行SQL语句
- 关闭资源(关闭Statement、Connection等)
public class Main {
private static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/xmg?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
";
private static final String USERNAME = "root";
private static final String PASSWORD = "root";
public static void main(String[] args) throws Exception {
test4();
// SQL Injection
// SQL注入问题
// String username = "";
// String password = "' OR '1' = '1";
// login2(username, password);
}
private static void login2(String username, String password) throws Exception {
/*
SELECT * FROM user WHERE username = '' AND password = '' OR '1' = '1'
SELECT * FROM user WHERE username = "" AND password = "' OR '1' = '1"
*/
String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
PreparedStatement pstmt = conn.prepareStatement(sql)) { // 3:编译、解析、优化
// 设置参数值
pstmt.setString(1, username);
pstmt.setString(2, password);
// 执行SQL语句
ResultSet rs = pstmt.executeQuery(); // 执行
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败,用户名或密码不正确");
}
}
}
private static void login1(String username, String password) throws Exception {
try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement()) {
String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = '" + password + "'";
System.out.println(sql);
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败,用户名或密码不正确");
}
}
}
private static void test4() throws Exception {
try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement()) {
String sql = "SELECT id myId, name myName FROM student";
ResultSet rs = stmt.executeQuery(sql); // 4:编译、解析、优化、执行
while (rs.next()) {
System.out.println(rs.getInt("myId"));
System.out.println(rs.getString("myName"));
// System.out.println(rs.getInt("age"));
// System.out.println(rs.getString("birthday"));
// System.out.println(rs.getString("phone"));
// System.out.println(rs.getString("email"));
// System.out.println(rs.getString("intro"));
System.out.println("---------------------");
}
}
}
private static void test3() throws Exception {
try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement()) {
String sql = "SELECT * FROM student";
ResultSet rs = stmt.executeQuery(sql);
// 让游标指向第1行记录
rs.next();
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getInt("age"));
System.out.println(rs.getString("birthday"));
System.out.println(rs.getString("phone"));
System.out.println(rs.getString("email"));
System.out.println(rs.getString("intro"));
System.out.println("---------------------");
// 让游标指向第2行记录
rs.next();
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getInt("age"));
System.out.println(rs.getString("birthday"));
System.out.println(rs.getString("phone"));
System.out.println(rs.getString("email"));
System.out.println(rs.getString("intro"));
}
}
private static void test2() {
// 0.数据库相关的信息
// JDK7开始,try-with-resources
try {
// Class.forName(driverClassName);
// DriverManager.registerDriver(new Driver());
try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement()) {
stmt.execute("UPDATE student SET age = 100 WHERE id = 1");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void test1() throws Exception {
// 0.数据库相关的信息
// String driverClassName = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/xmg?serverTimezone=UTC";
String username = "root";
String password = "root";
// 1.注册Driver到DriverManager
// Class.forName(driverClassName);
// DriverManager.registerDriver(new Driver());
// 2.利用DriverManager创建数据库连接
Connection conn = DriverManager.getConnection(url, username, password);
// 3.利用Connection创建Statement
Statement stmt = conn.createStatement();
// 4.利用Statement来执行SQL语句
stmt.execute("UPDATE student SET age = 100 WHERE id = 1");
// 5.关闭资源
stmt.close();
conn.close();
}
}
JDBCurl要加上参数useSSL=falseJDBC6.0 url要加上参数serverTimezone=UTCSystem.out.println(rs.getInt("id"));标签名有别名的时候,应该传入别名。
PreparedStatement
PreparedStatement接口继承自Statement接口
建议使用PreparedStatement替代Statement
PreparedStatement的有点
- 可以防止SQL注入
- 执行速度比Statement快
- 支持批量处理
配置文件
一些经常动态修改的值,建议放入到配置文件中,不要写死在Java代码中
db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/crm
username=xxx
password=xxx
db.xml
<?xml version="1.0" encoding="UTF-8"?>
<db>
<url>jdbc:mysql://localhost:3306/crm</url>
<username>xxx</username>
<password>xxx</password>
</db>
数据库连接池
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import java.util.Properties;
public class Dbs { private static DataSource ds; static { try (InputStream is = Dbs.class.getClassLoader().getResourceAsStream("druid.properties")) { Properties properties = new Properties(); properties.load(is); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } }
/**
* 执行DDL、DML语句
*/
public static int update(String sql, Object ...args) {
try {
Connection conn = ds.getConnection();
// 从数据库获取所有的客户数据
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置参数
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}
// 执行
return pstmt.executeUpdate();
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public static <T> List<T> query(String sql, RowMapper<T> mapper, Object ...args) {
if (mapper == null) return null;
try {
Connection conn = ds.getConnection();
// 从数据库获取所有的客户数据
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置参数
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}
// 执行
List<T> array = new ArrayList<>();
try (ResultSet rs = pstmt.executeQuery()) {
for (int row = 0; rs.next(); row++) {
array.add(mapper.map(rs, row));
}
}
return array;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 用来执行每一行数据的映射(rs -> bean)
* @param <T>
*/
public interface RowMapper<T> {
T map(ResultSet rs, int row) throws Exception;
}
}
Spring JDBC
核心类:JdbcTemplate
public class Dbs {
private static JdbcTemplate tpl;
static {
try (InputStream is = Dbs.class.getClassLoader().getResourceAsStream("druid.properties")) {
Properties properties = new Properties();
properties.load(is);
DataSource ds = DruidDataSourceFactory.createDataSource(properties);
tpl = new JdbcTemplate(ds);
} catch (Exception e) {
e.printStackTrace();
}
}
public static JdbcTemplate getTpl() {
return tpl;
}
}
总结
-
显示注册驱动,将Driver注册到DriverManager(JDBC 4.0后可选) ---> 从DriverManager获取Connection ---> 从Connoction获取Statement/PreparedStatement ---> 执行SQL获取ResultSet --->ResultSet的next方法 --> 关闭资源(关闭Connection、Statement、ResultSet)
-
使用数据库连接池Druid: DataSourceFactory创建DataSource(DruidDataSourceFactory.createDataSource(properties);)--> 从DataSource获取Connection 每个sql都要创建链接、关闭链接)---> 从Connoction获取Statement/PreparedStatement ---> 执行SQL获取ResultSet --->ResultSet的next方法 --> 关闭资源(关闭Statement、Connection)
-
Spring JDBC,连接池用Druid: DataSourceFactory创建DataSource(DruidDataSourceFactory.createDataSource(properties);)--> 从DataSource获取 JDBCTemplate (JDBCTemplate最好全局只有一份)--> JDBCTemplate执行sql (自动去处理一些低级细节,比如异常处理,打开和关闭资源)