JDBC:Java DataBase Connection
JDBC连接步骤:
1.导包 mysql / ojdbc
2.加载驱动/类 Class.forName(“类名”);
3.获得连接对象 Co nnection (三要素:url,username,password)
4.获得执行SQL语句的Statement对象
5.执行SQL语句,如果有ResultSet,处理结果集
6.关闭连接
一、JDBC小列子:
1.简单的注册和登陆
/*
* 注册
*/
public class JDBCDemo03 {
public static void main(String[] args) {
// 注册功能 - insert
Scanner console = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = console.next();
System.out.println("请输入密码:");
String password = console.next();
// 连接数据库,执行insert语句
try {
// jdbc中的连接,事务是默认自动提交
Connection con = JDBCUtils.getConnection();
// 设置不自动提交事务 - 默认是true
con.setAutoCommit(false);
Statement stmt = con.createStatement();
String sql = "insert into user_bao values(seq_user_bao.nextval, '"
+ username
+ "', '"
+ password
+ "')";
System.out.println(sql);
stmt.executeUpdate(sql);
// 手动提交
// con.commit();
/*
* con.rollback(); // 手动回滚
* -- 保存事务点
* Savepoint savepoint = con.setSavepoint();
* -- 回滚到上面保存的事务点
* con.rollback(savepoint);
*/
System.out.println("注册成功!");
con.close(); // 关闭连接会自动提交
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/*
* 登陆
*/
public class JDBCDemo02 {
public static void main(String[] args) {
// 用户登录 - 控制台输入用户名密码
Scanner console = new Scanner(System.in);
System.out.println("请输入用户名:");
// 随意
String username = console.nextLine();
System.out.println("请输入密码:");
// a' or 'c'='c - 可以登录成功
String password = console.nextLine();
// 提示是否登录成功 - 查询
String sql = "select * from user_bao where username='"
+ username
+ "' and password='"
+ password
+ "'";
// 查询结果:要么一条,要么null
System.out.println(sql);
Connection conn = JDBCUtils.getConnection();
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
二、事务管理的sql注入问题与预编译解决
上面的注册登录例子使用的是简单statement,因此会出现sql注入问题,使得安全不能得到保障。如密码为 a’ or ‘b’='b -> 恒成立 => sql注入
为了解决sql注入,可以使用PreparedStatement 预编译的,即将不完整的sql语句,进行编译(确定sql语句的语法结构)
示例代码:
String sql = "select * from user_bao where username=? and password=?";
Connection conn = JDBCUtils.getConnection();
// 获得预编译的Statement
try {
PreparedStatement stmt = conn.prepareStatement(sql);
// 传入参数,根据位置传参数,比如1对应username,2对应password,前面sql语句中问号处
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
} catch (SQLException e) {
e.printStackTrace();
}
Statement: 每次执行 都会有新的sql语句编译+执行
PreparedStatement: select * from user where name=? and pwd=?
结构一样的sql语句,预编译
多次执行,预编译只有一次,每次只需要传参,执行
综合考虑,建议使用PreparedStatement
三、批量导入- sql - insert
在数据库操作时,如果同时插入大量数据,会使得效率降低。因此使用批量操作队列stmt.addBatch()与stmt.clearBatch()可以帮助提高数据库插入效率。
示例代码:
/*
* 批量操作
*/
public class JDBCDemo05 {
public static void main(String[] args) throws SQLException {
// 模拟批量操作 - 后台管理系统
String sql = "insert into student_bao values(seq_stu_bao.nextval, ?,?,? )";
Connection conn = JDBCUtils.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
long time1 = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
stmt.setString(1, "name"+i);
stmt.setString(2, "pwd"+i);
stmt.setString(3, "no"+i);
// stmt.executeUpdate();
// 加入批量操作队列中
stmt.addBatch();
}
// 统一执行批量操作队列中的sql语句
stmt.executeBatch();
// 清除队列中的sql语句
stmt.clearBatch();
long time2 = System.currentTimeMillis();
System.out.println(time2 - time1);
conn.close();
}
}
四、JDBCUtils的封装
将JDBC连接步骤封装起来,方便后续对代码的修改。
示例代码:
public class JDBCUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
//在静态方法执行之前就需要完成的就写在静态代码块中
static {
Properties pro = new Properties();
try {
pro.load(new FileInputStream(JDBCUtils.class.getResource("db.properties").getFile()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
}
public static Connection getConnection() {
Connection con = null;
try {
Class.forName(driver);
con = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
}
db.properties
# driver
#driver = oracle.jdbc.driver.OracleDriver
driver = com.mysql.jdbc.Driver
# url
#url = jdbc:oracle:thin:@192.168.6.66:1521:orcl
# mysql - url jdbc:mysql://localhost:3306/java1903
url = jdbc:mysql:///java1903
# username
#username = student
username = root
# password
password = 123456
#password = 123456
五、总结
JDBC连接步骤:
1.导包 mysql / ojdbc(两个都可以,可以用maven进行封装)
2.加载驱动/类 Class.forName(“类名”);
3.获得连接对象 Co nnection (三要素:url,username,password)(最好将连接过程封装成JDBCUtils已经配置文件,方便后续修改,四个要素—驱动、url、username、password)
4.获得执行SQL语句的Statement对象(使用预编译的prepareStatement,避免产生sql注入)
5.设置参数(为prepareStatement?占位符设置参数)
6.执行SQL语句,如果有ResultSet,处理结果集
7.使用next()方法遍历结果集
8.关闭连接
(批注:批量注入时可以选择使用批量操作队列addBatch()与clearBatch()来方便操作)