1 JDBC:一套访问数据库的规范(就是一组接口),并提供连接数据库的协议标准,然后各个数据库厂商会遵循SUN的规范提供一套访问自己公司的数据库服务器的API出现。即每个公司的数据库类都实现了SUN公司的JDBC接口!
2 使用JDBC涉及到的类:
Class:使用该类中的forName方法来加载驱动类;
Connection:数据库连接对象;
DriverManager:用于管理JDBC驱动的服务类;
Statement:用于执行SQL语句的工具接口;
ResultSet:结果集对象。
3 使用JDBC四步走:
1,加载驱动类;
2,获得数据库连接;
3,使用数据库连接获得Statement对象;
4,使用sql语句,调用Statement对象的executeQuery()来得到ResultSet结果集对象。
4 规范化代码:
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/exam";
String username = "root";
String password = "123";
Class.forName(driverClassName);
con =DriverManager.getConnection(url, username, password);
stmt = con.createStatement();
String sql = "select * from emp";
rs = stmt.executeQuery(sql);
/*
* 循环遍历rs,打印其中数据
*/
int count = rs.getMetaData().getColumnCount();
while (rs.next()) {
for (int i = 1; i <= count; i++) {
System.out.println(rs.getString(i));
if (i < count) {
System.out.println(", ");
}
}
System.out.println();
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (con != null)
con.close();
}
5 PreparedStatement的用法:
5.1 防止SQL注入:
例子:当登录时输入登录名和密码如"a' or'a'='a",就会输入true然后成功登录,用PreparedStatement可以防止SQL注入;
使用PreparedStatement的例子:
String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc.mysql://localhost:3306/mydb3";
String mysqlUsername = "root";
String mysqlPassword = "123";
Class.forName(driverClassName);
Connectioncon = DriverManager.getConnection(url, mysqlUsername, mysqlPassword);
/**
* 使用PreparedStatement
*1,给出sql模板:所有的参数使用?来替代;
*2,调用Connection方法,得到PreparedStatement
*/
Stringsql = "select * from t_user where username=? and password=?";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, "lisi");
pstmt.setString(2, "123");
ResultSet rs = pstmt.executeQuery();
return rs.next();
5.2 预处理的原理:
5.2.1 服务器的工作:
校验sql语句的语法
编译:一个与函数相似的东西
执行:调用函数
5.2.2 PreparedStatement的优点:
* 前提:连接的数据库必须支持预处理!现在几乎没有不支持的!
* 每个pstmt都与一个sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译,执行时只是把参数传递过去而已!
* 若二次执行时,就不用再次校验语法,也不用再次编译!直接执行!
6 JdbcUtils1.0版本小工具的实现:
public class JdbcUtils {
private static Properties props = null;
//只在JdbcUtils类被加载时执行一次
static {
//给props进行初始化,即加载dbconfig.properties文件到props对象中
try {
/**
* 1,加载配置文件;
* 2,加载驱动类;
* 3,调用DriverManage.getConnection()
*/
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbconfig.properties");
Properties props = new Properties();
props.load(in);
} catch (IOException e) {
throw newRuntimeException(e);
}
//加载驱动类
try {
Class.forName(props.getProperty("driverClassName"));
} catch (ClassNotFoundException e) {
throw newRuntimeException(e);
}
}
//获取连接
public static Connection getConnection() throws SQLException {
//得到连接
return DriverManager.getConnection(props.getProperty("url"),
props.getProperty("username"),
props.getProperty("password"));
}
}
7 数据库类型与java中类型的对应关系:
DATE->java.sql.Date
TIME->java.sql.Time
TIMESTAMP->java.sql.Timestamp
8 批处理:
例子:
Connection con = JdbcUtils.getConnection();
String sql = "insert into t_stu values(?,?,?,?)";
PreparedStatement pstmt = con.prepareStatement(sql);
for(int i = 0; i < 10000; i++) {
pstmt.setInt(1, i + 1);
pstmt.setString(2, "stu_" + i);
pstmt.setInt(3, i);
pstmt.setString(4, i % 2 == 0 ? "男" : "女");
pstmt.addBatch();
}
pstmt.executeBatch();
注意点:一定要在JDBC的url最后面添加问号后添加如下语句,
rewriteBatchedStatements\=true
完整的url示例:
url=jdbc\:mysql\://localhost\:3306/mydb3?rewriteBatchedStatements\=true