JDBC Java database connectivity
翻译:Java连接数据库
是Java定义的一套规范(接口)
- 导入数据库驱动jar包,右键依赖项目;
- 加载驱动jar包(反射);
- 获取连接对象 ;
- 获取操作对象;
项目下新建lib文件夹,导入jar包,右键依赖于项目。
package com.westos.demo;
import java.sql.*;
public class JdbcDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载驱动,注册驱动这个操作是Driver中的静态代码块作的,DriverManage.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//数据库连接到mydb库
String url = "jdbc:mysql://localhost:3306/mydb";
//用户名
String username = "root";
//密码
String password = "123456";
//获取连接对象
Connection connection = DriverManager.getConnection(url, username, password);
//sql语句,查询user表
String sql = "select * from user";
//获取操作对象
Statement statement = connection.createStatement();
//执行sql查询语句,返回ResultSet结果集对象
ResultSet resultSet = statement.executeQuery(sql);
//遍历打印
while (resultSet.next()){
String string = resultSet.getString(2);
System.out.println(string);
}
//释放资源
connection.close();
statement.close();
}
}
上面获取的操作对象不能防范sql注入攻击
当要添加条件查询时候,需要拼串,凡是涉及到字符串拼接的都不能防范sql注入攻击。
假如如下查询用户表验证身份,但是用户可以输入特殊的串比如String username1="1'='1' or '1'='1";
来构造恒为真的条件。
为了解决这种通过拼串造成的sql注入,Java提供了预编译操作对象,通过传值来解决。
例如:
package com.jingfei.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class SqlTest2 {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection=DriverManager.getConnection("jdbc:mysql:///mydb", "root", "123456");
String username="bob";
String password="123456";
String username1="1'='1' or '1'='1";
String password1="1'='1' or '1'='1";
String sql1="select * from users where username=? and password=?";
//获取预编译操作对象
PreparedStatement statement=connection.prepareStatement(sql1);
statement.setString(1, username1);
statement.setString(2, password1);
ResultSet resultSet=statement.executeQuery();
if(resultSet.next()){
String name =resultSet.getString("username");
String pwd=resultSet.getString("password");
System.out.println("登陆成功"+name+"=="+pwd);
}else {
System.out.println("登陆失败");
}
}
}
这样就防止了sql注入。
操作对象statement中的方法
- 1、execute()
- 2、executeUpdate();
用来执行DML语句,对表中数据增删改。 - 3、executeQuery();
用来执行DQL语句,返回ResultSet结果集对象。
用ResultSet中的next作为判断条件,判断查出的数据是否还有下一个。
用ResultSet中的getxxxx来取值,参数为列表的次序号(第一列就为1,第二列就为2),或者写列名。
批处理
如果有大量数据,每存一次执行一个太慢了,就引进批处理。
批处理向用户表中插入数据
package com.jingfei.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class BatchTest {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection=DriverManager.getConnection("jdbc:mysql:///mydb", "root", "123456");
String sql1="insert into users values(?,?)";
//获取预编译操作对象
PreparedStatement statement=connection.prepareStatement(sql1);
for (int i = 0; i < 100; i++) {
String username1="jenry"+i;
String password1="admin"+i;
//给?设置值
statement.setString(1, username1);
statement.setString(2, password1);
//添加批处理,相当于放在了缓存中,并没有执行。
statement.addBatch();
}
//执行批处理
statement.executeBatch();
//清空缓存
statement.clearBatch();
//释放资源
connection.close();
statement.close();
}
}
添加成功。
JDBC调用存储过程或自定义函数
创建存储过程。输入姓名,返回密码。
DELIMITER $$
CREATE
PROCEDURE `mydb`.`proce2`(IN username VARCHAR(32),OUT pwd VARCHAR(32))
BEGIN
SELECT users.`password` INTO pwd FROM users WHERE users.`username`=username;
END$$
DELIMITER ;
Java调用
package com.jingfei.sql;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;
public class CallProc {
public static void main(String[] args) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection connection=DriverManager.getConnection("jdbc:mysql:///mydb", "root", "123456");
String sql1="{call proce2(?,?)}";
CallableStatement statement=connection.prepareCall(sql1);
String username="bob";
statement.setString(1, username);
//注册第二个参数为输出参数,并设置参数类型,如果类型为null,则设置为Types.null
statement.registerOutParameter(2, Types.VARCHAR);
statement.execute();
//返回拿到第二个参数的值
String pwd = statement.getString(2);
System.out.println(pwd);
}
}
谢谢