简单介绍完JDBC API中各类与方法用处之后,接下来开始进行JDBC编程开发
大致分为6个步骤
package com.MrLiu.group.jdbc;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
public class ConnectionTest {
private static String Name ;
private static String PassWorld ;
private static String URL ;
private static String Driver;
//静态代码块加载驱动,类加载即被加载
static {
try {
///使用Properties类加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream(filePath));
Name = properties.getProperty("name");
PassWorld = properties.getProperty("passWorld");
URL = properties.getProperty("url");
Class.forName(properties.getProperty("driver"));
}catch (Exception e){
System.out.println("驱动加载失败"+e.getMessage());
}
}
public static void main(String[] args) throws Exception{
//通过DriverManager获取连接
Connection connection = DriverManager.getConnection(URL, Name, PassWorld);
//创建Statement对象
Statement statement = connection.createStatement();
//执行SQL
/* 第一种SQL execute() 可执行所有SQL语句,返回一个布尔类型的值,执行后第一个结果为 RowSet 返回true
* 第二种SQL executeQuery() 执行查询语句 返回RowSet结果集
* 第三种SQL executeUpdate 执行DML语句 返回结果表示受影响的行数
* */
//添加记录
int row = statement.executeUpdate("insert stu_test(name,age,class) value ('小明',21,3)");
System.out.println("受影响行数为=="+row);
//查询记录 返回 RowSet结果集
ResultSet resultSet = statement.executeQuery("select * from stu_test where class = 2");
while (resultSet.next()){
//RowSet中 getXxx(int columnIndex) 方法表示获取当前行记录第 columnIndex 个字段对应Xxx类型的值
System.out.println("学生名称为 :" + resultSet.getString(2) + "\n" +
"学生年龄为 :" + resultSet.getInt(3) + "\n" +
"学生班级为 :" + resultSet.getInt(4) );
}
resultSet.close();
statement.close();
connection.close();
}
}
对于如下两条SQL语句,结构相同,执行的字段参数不同的时候,可以使用带 ‘?’ 作为占位符 的SQL语句代替
insert into stu_test(name,age,class) value('小红',20,2);
insert into stu_test(name,age,class) value('小红',20,2);
.......
//创建预编译Statement对象
PreparedStatement statement = connection.prepareStatement("insert into stu_test(name,age,class) value (?,?,?)");
for (int i = 0; i < 5; i++) {
statement.setObject(1,"张三"+i);
statement.setObject(2,i + 20);
statement.setObject(3,i);
statement.executeUpdate();
}
执行完查看数据看可以看到执行结果
对于Statement执行循环插入记录操作,带占位符的预编译SQL执行效率更高
预编译SQL另一个作用就是能够防止SQL注入 代码如下
package com.MrLiu.group.jdbc;
import javax.swing.*;
import java.awt.*;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
public class ConnectionTest {
private static String Name ;
private static String PassWorld ;
private static String URL ;
private static String Driver;
//登录界面
private static JFrame loginUi = new JFrame("Login");
private JTextField userName = new JTextField(40);
private JTextField passWorld = new JTextField(40);
private JButton button =new JButton("Login");
public void driverClass(){
try {
///使用Properties类加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("properties"));
Name = properties.getProperty("name");
PassWorld = properties.getProperty("passWorld");
URL = properties.getProperty("url");
Class.forName(properties.getProperty("driver"));
//登录按钮监听
button.addActionListener( e -> {
try {
if (getConnection(userName.getText(),passWorld.getText())){
dialog("登录成功");
}else{
dialog("登录失败");
}
}catch (Exception e1){
e1.printStackTrace();
}
});
loginUi.add(userName, BorderLayout.NORTH);
loginUi.add(passWorld);
loginUi.add(button,BorderLayout.SOUTH);
loginUi.pack();
loginUi.setVisible(true);
}catch (Exception e){
System.out.println("驱动加载失败"+e.getMessage());
}
}
public static void dialog(String message){
JOptionPane.showMessageDialog(loginUi,message);
}
public static boolean getConnection(String userName,String passWorld) throws Exception{
//创建查询Sql
String sql = "select * from stu_test where name = '"+userName+"' and class = '"+passWorld+"'";
//通过DriverManager获取连接
Connection connection = DriverManager.getConnection(URL, Name, PassWorld);
//创建Statement对象
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if (!resultSet.next()){
return false;
}else{
return true;
}
}
public static void main(String[] args) throws Exception{
new ConnectionTest().driverClass();
}
}
使用Statement时无法防止上面这种 输入 ‘or true or’ 仍能登录成功的情况
所以此时换成预编译Statement时,会发现输入 ‘or true or’ 后显示的为正常登录失败情况
........
//创建查询Sql
String sql = "select * from stu_test where name=? and class=?";
System.out.println(sql);
//通过DriverManager获取连接
Connection connection = DriverManager.getConnection(URL, Name, PassWorld);
PreparedStatement statement = connection.prepareStatement(sql);
statement.setObject(1,userName);
statement.setObject(2,passWorld);
ResultSet resultSet = statement.executeQuery();
.........
原因在于前者的SQL 为
select * from stu_test where name =' 'or true or' ' and class =' '
输入的为true 成为 了直接量,使得用户可以直接登录
所以预编译Statement的好处在于