jdbc概念
jdbc:Java数据库连接技术(Java DataBase Connectivity)
能实现java程序对各种数据库的访问
由一组使用Java语言编写的接口(java api)和类组成,位于java.sql和javax.sql包
面向接口编程
常用类:DriverManager
常用接口:Connection PrepareStatement ResultSet Statement
mysql、oracle、sqlserver厂商提供jar包来具体实现jdbc的接口
通过jdbc连接数据库
jdbc的优点
不必为不同的数据库专门编写不同的程序,而只需要加载不同的数据库驱动即可
前提:导包
1、Class.forName(String)加载驱动
2、获得数据库连接(Connection)
3、创建Statement/PrepareStatement对象,执行sql语句
4、返回并处理执行结果(若执行查询操作,返回ResultSet)
5、释放资源
public class Test {
public static void main(String[] args) throws Exception {
//导入jar包
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2获取连接 数据库地址URL 用户名 密码
String url = "jdbc:mysql://192.168.232.234:3306/test";//虚拟机IP 库名
//相当于登录
Connection conn = DriverManager.getConnection(url, "root", "ok");
//3执行增删改查等操作
Statement stat = conn.createStatement();
String sql = "select * from grade";
//ResultSet 是结果集
ResultSet rs = stat.executeQuery(sql);
while (rs.next()) {//相当于指针 一行一行去遍历
//如何取出每一列的值
//如果第一列是int类型 getInt(1)
int gradeId = rs.getInt(1);
//如果第二列是String类型 getString(2)
String gradeName = rs.getString(2);
System.out.println(gradeId + "\t|\t" + gradeName);
}
//但是有个问题 如果有很多列 按照第几列来遍历会不明确
//可以根据列名来获取值 推荐使用
while (rs.next()) {
int gradeId = rs.getInt("GradeID");
String gradeName = rs.getString("GradeName");
System.out.println(gradeId + "\t|\t" + gradeName);
}
//4关闭资源 先使用的后关
rs.close();
stat.close();
conn.close();
}
}
补充说明
Class.forName(“com.mysql.jdbc.Driver”);
根据字符串找到Driver.class类,然后将类的信息加载到java虚拟机jvm,然后将驱动类实例化
与Driver d =new Driver(); 作用相同
Driver d =new Driver();先加载:先将类信息加载到java虚拟机中,然后创建对象
Class.forName(“com.mysql.jdbc.Driver”);后加载:事先不知道类的信息,在运行期间才知道要使用哪个类,去创建获取类的相关信息包括创建对象、获取类的方法、获取类的属性等(反射机制)
Connection conn = DriverManager.getConnection(url, “root”, “ok”);
将Driver实例放到DriverManager驱动管理器中,通过getConnection方法来获得数据库连接
Statement 和PreparedStatement
查看文档,PreparedStatement是Statement的子接口
Statement由方法createStatement()创建,该对象用于发送简单的SQL语句
PreparedStatement由方法prepareStatement()创建,该对象用于发送带有一个或者多个输入参数的SQL语句
SQL语句使用“?”作为数据占位符
使用setXxx()方法设置数据
PreparedStatement—预编译
效率、性能、开销
安全性
代码可读性
改一下需求
查询特定姓名的学生信息
用Statement的局限性 sql注入
public class Test {
public static void getStudentByName(String name)throws Exception{
//导入jar包
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2获取连接 数据库地址URL 用户名 密码
String url = "jdbc:mysql://192.168.232.234:3306/test";//虚拟机IP 库名
//相当于登录
Connection conn = DriverManager.getConnection(url, "root", "ok");
//3执行增删改查等操作
Statement stat = conn.createStatement();
String sql = "select * from student where stu_name='"+name+"'";
ResultSet rs = stat.executeQuery(sql);
while (rs.next()) {
int i=1;
while (rs.getMetaData().getColumnCount() >= i) {
System.out.print(rs.getObject(i)+"\t|");
i++;
}
System.out.println();
}
//4关闭资源
rs.close();
stat.close();
conn.close();
}
public static void main(String[] args) throws Exception {
getStudentByName("李白' or '1'='1");
}
}
这里查询出全部学生的信息
使用PreparedStatement
public class Test {
public static void getStudentByName(String name)throws Exception{
//导入jar包
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2获取连接 数据库地址URL 用户名 密码
String url = "jdbc:mysql://192.168.232.234:3306/test";//虚拟机IP 库名
//相当于登录
Connection conn = DriverManager.getConnection(url, "root", "ok");
//3执行增删改查等操作
String sql = "select * from student where stu_name=?";//占位符
PreparedStatement stat = conn.prepareStatement(sql);//创建PreparedStatement对象时sql作为参数
//在sql语句的第一个问号的位置填充name
stat.setString(1,name);//填充第一个问号 值的类型是String
System.out.println(sql);
ResultSet rs = stat.executeQuery();
while (rs.next()) {
int i=1;
while (rs.getMetaData().getColumnCount() >= i) {
System.out.print(rs.getObject(i)+"\t|");
i++;
}
System.out.println();
}
//4关闭资源
rs.close();
stat.close();
conn.close();
}
public static void main(String[] args) throws Exception {
getStudentByName("李白");
//getStudentByName("李白' or '1'='1");
}
}
拼接sql注入,没有显示
补充说明
Statement 是将sql语句发给数据库管理系统DBMS,然后DBMS对sql语句进行编译、语法的检查等,然后执行
PreparedStatement -预编译 将sql语句先进行语法的检查和编译,再交给DBMS执行
使用属性
public class TestPrepare {
private static Connection conn;
private static PreparedStatement pst;
private static ResultSet rs;
private static final String URL="jdbc:mysql://192.168.232.234:3306/test";
public static void getConn(){
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
conn= DriverManager.getConnection(URL,"root","ok");
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void query(String sql,String...params){
try {
pst=conn.prepareStatement(sql);
//遍历参数 将参数加到对应的问号位置 问号是从1开始
for (int i = 0; i < params.length; i++) {
pst.setObject(i+1,params[i]);
}
rs=pst.executeQuery();
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean update(String sql,String...params){
int num=0;
try {
pst=conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pst.setObject(i+1,params[i]);
}
//增删改 返回受影响的行数
num=pst.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return num>0?true:false;
}
public void close() {
try {
if (null!=rs) {
rs.close();
}
if (null!=pst) {
pst.close();
}
if (null!=conn) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
getConn();
String s="update subject set subjectNo=?,GradeId=? where subjectName=? ";
update(s,"9","2","高等数学-2");
String s1="select * from subject where GradeId=?";
query(s1,"2");
while (rs.next()) {
int i=1;
//getMetaData 获取表结构 getColumnCount获取列数
while (rs.getMetaData().getColumnCount() >= i) {
System.out.print(rs.getObject(i)+"\t|");
i++;
}
//获取一行数据之后换行
System.out.println();
}