JDBC操作数据库六部曲
-
导入jar包.
-
项目新建一个lib文件夹,将准备好的jar包复制进来.
-
右键jar包,点击Build Path添加到项目中
-
-
加载驱动
常用的就是通过反射加载
Class.forname("com.mysql.jdbc.Driver"); ---------------------------------- 将jar包反编译,查看Driver类中有这么一段代码 static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } 可以看到其实是是一个静态代码块中进行了注册驱动. 所以我们也可以这样加载 Driver d=new Driver(); Drivermanager.registerDriver(d);
-
创建数据库连接对象
Connection con=DriverManager.getConnection(url,user,password); 其中,url就是连接到的数据库的地址,包括端口\数据库名 user就是你数据库登录名 password就是数据库登录密码
-
创建数据库操作对象
1.Statement数据库操作对象一般用来操作静态sql语句(不推荐) Statement statement=con.createStatement(); 2.PreparedStatement是一种预处理操作对象,可以处理动态sql语句方便(推荐) PreparedStatement ps=con.prepareStatement(sql)//sql是数据库操作语句
-
执行sql语句,将数据操作到MySql中
如果操作的语句是DML语句(增\删\改)(insert\delete\update) 通过数据库操作对象调用executeUpdate()方法 int result=statement.executeUpdate(sql)//返回的结果就是影响数据库中的行数 int result=prepareStatement.executeUpdate()//不传入参数
-
关闭连接
从小关到大.最好写在finally代码块中 finally { // 6.关闭连接(从小关到大) try { if(statement!=null) { statement.close(); //关闭数据库操作对象 } if(connection!=null) { connection.close(); //关闭数据库连接对象 } } catch (SQLException e) { e.printStackTrace(); } }
下面是完整代码
注意:在导入包的时候,注意是要导入java.sql的包.如果加载驱动不通过反射,而是自己创建Driver对象注册的话,调用的是com.mysql.jdbc.Driver包.
Statement数据库操作对象
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import com.mysql.jdbc.Driver;//什么Driver去加载驱动时,要用到的包 /* * 连接Mysql的6步操作 */ public class TestJdbc { public static void main(String[] args) { // 1.导入jar包。在项目中新建一个外键夹(lib),将jar包添加进去。 // 再右键build path添加到项目中。之后在整个项目中旧可以直接使用 // jar包里面也是一些java代码,就是连接数据库进行操作的代码封装好 Connection connection = null; // 数据库连接对象 Statement statement = null; // 数据库操作对象 try { // 2.加载驱动;讲Driver.class加载到jvm中。Driver类中有一个静态代码块,用于注册驱动 //Class.forName("com.mysql.jdbc.Driver"); Driver d=new Driver(); DriverManager.registerDriver(d); //这两句相当于 Class.forname("com.mysql.jdbc.Driver") // 3.创建数据库连接对象 // 连接哪一个数据库,ip、端口、数据库名称. // String url="jdbc:mysql://127.0.0.1:3306/test"; //连接到本机数据库 String url = "jdbc:mysql://localhost:3306/test"; // 这个也是连接到数据库 String user = "root"; // 本地数据库用户名 String password = "123456"; // 本地数据库密码 // 通过一个静态方法,获取一个和数据库的连接 connection = DriverManager.getConnection(url, user, password); System.out.println("数据库连接成功!"); // 获取连接成功 // 4.通过连接对象,创建一个Statement数据库操作对象 statement = connection.createStatement(); System.out.println("获取数据库操作对象成功"); // 5.执行sql语句,将sql语句提交到数据库 String sql = "insert into user(username,password) values('xixi',123456)"; // 通过操作数据库的对象statement,去执行sql语句,真正将数据添加到数据库 int result = statement.executeUpdate(sql);// 返回的这个result,就是证明了影响了多少条数据库里面的数据 if (result > 0) { System.out.println("插入数据成功!"); } else { System.out.println("插入数据失败!"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 6.关闭连接(从小关到大) try { if(statement!=null) { statement.close(); //关闭数据库操作对象 } if(connection!=null) { connection.close(); //关闭数据库连接对象 } } catch (SQLException e) { e.printStackTrace(); } } } }
PreparedStatement预处理操作数据库对象(推荐),使用较方便,动态sql语句随便搞,还能防止sql注入
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Scanner;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestPrepareStatementUpdate {
public static void main(String[] args) {
// 1.添加jar包
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
Scanner sc = new Scanner(System.in);
System.out.print("请输入要修改的用户id:");
int id = sc.nextInt();
System.out.print("请输入要修改的密码:");
String pass = sc.next();
// sql语句,?表示占位符
String sql = "update user set password=? where id=?";
Connection connection = null;
PreparedStatement ps = null;
try {
// 2.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.创建数据库连接对象
connection = DriverManager.getConnection(url, user, password);
System.out.println("创建数据库连接对象成功");
// 4.创建数据库操作对象prepareStatement
ps = connection.prepareStatement(sql);
// 为占位符?赋值
ps.setString(1, pass);
ps.setInt(2,id);
// 5.执行sql语句将数据修改到数据库
int result = ps.executeUpdate();
if (result > 0) {
System.out.println("修改成功!");
} else {
System.out.println("修改失败!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC操作DQL(查询操作)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
public static void main(String[] args) {
// 1.添加jar包(如果添加过了就不需要)
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String pass = "123456";
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 2.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.获取连接对象
con = DriverManager.getConnection(url, user, pass);
String sql = "select id pid,name,age,sex from person";
// 4.获取操作数据库对象,prepareStatement是一个预处理对象
ps = con.prepareStatement(sql);
// 5.执行查询获取结果集,就是查找到的所有数据
rs = ps.executeQuery();//注意这里是没有传入sql语句做参数。因为在获取预处理对象的时候已经传入
// rs = ps.executeQuery(sql); //可以使用,但是只能书里没有参数的sql语句。不推荐使用。例如如果在做登陆的时候,需要根据用户输入的信息去查询,旧不适用
// rs.next()类似于迭代器。这里返回一个boolean值,是判断是否有下一列,并将当前指向的数据返回
while (rs.next()) {
//获取得到的对象有两种范式:1.根据数据所在的列数获取(不推荐);2.根据数据的别名、别名、别名来获取(推荐)
int id = rs.getInt(1);// 获取第一列的值
String name = rs.getString(2);// 获取第二列的值
int age = rs.getInt(3);// 获取第三列的值
String sex = rs.getString(4);// 获取第四列的值
// int id=rs.getInt("pid");//通过别名获取(推荐)注意是别名,不是字段名
// String name=rs.getString("name");
// int age=rs.getInt("age");
String sex=rs.getString("sex");
//获取所有的列,组合起来就是一条数据
System.out.println("id:" + id + ", name:" + name + ", age:" + age + ", sex:" + sex);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
当然有好多代码可以做封装,这里就不展示了.
什么是sql注入呢?
就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器
执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引
擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据
库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过
WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。
看一下我写的一个例子,不知道准不准确
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;
/*
* SQL注入.
*/
public class TestSqlZR {
public static void main(String[] args) throws IOException {
//获取一个类加载器
ClassLoader classLoader = TestSqlZR.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("db.properties");
Properties pt=new Properties();
pt.load(is);
String url = pt.getProperty("url");
String user=pt.getProperty("user");
String password=pt.getProperty("password");
Connection con=null;
Statement statement=null;
ResultSet rs=null;
Scanner sc=new Scanner(System.in);
System.out.println("请输入用户名:");
String name=sc.nextLine();
System.out.println("请输入密码:");
String pass=sc.nextLine();
//只要用户名输入正确,就能进行登陆
String sql="select username,password from user where username='"+name+"' and (password='"+pass +"' or 1=1)";
System.out.println(sql);
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//创建连接对象
con=DriverManager.getConnection(url,user,password);
//创建数据库操作对象
statement = con.createStatement();
//获取结果集
rs = statement.executeQuery(sql);
if(rs.next()) {
System.out.println("登陆成功");
}
else {
System.out.println("登陆失败");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(rs!=null)
rs.close();
if(statement!=null)
statement.close();
if(con!=null)
con.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
大概的意思就是即使你密码不正确,也能登录成功
批处理
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
/*
* PreparedStatement的批量操作
*/
public class TestBatch1 {
public static void main(String[] args) {
//1.添加jar包
String url="jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true";
String user="root";
String password="123456";
Connection con=null;
PreparedStatement ps=null;
String sql="insert into person(name,age,sex) values(?,?,?)";
try {
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection(url,user,password);
ps=con.prepareStatement(sql);
long start=System.currentTimeMillis();
for(int i=1;i<10000;i++) {
ps.setString(1, "jack"+i);
ps.setInt(2, i);
ps.setString(3, "男"+i);
//添加到批处理
ps.addBatch();
if(i%500==0) {
//当数据达到500条的时候,执行批处理操作
// int[] executeBatch = ps.executeBatch();//返回值代表处理完影响的行数
ps.executeBatch();
//清空批处理
ps.clearBatch();
System.out.println("处理完成"+i+"条");
}
}
ps.executeBatch();
ps.clearBatch();
long end=System.currentTimeMillis();
System.out.println("批量插入1000条数据成功!花费时间:"+(end-start));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
注意:进行批处理的时候,一定要在url后面添加上rewriteBatchedStatements=true.真正添加上这一句,才是真正的批处理,否则还是一条一条sql进行操作.
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true
顺便记录一下设置utf8编码格式
将数据库连接\加载\关闭进行封装
/*
* properties文件配置url.user,password
*/
public class DBUtilProperties {
static String url;
static String user;
static String password;
static {
try {
//获取类加载器
ClassLoader classLoader = DBUtilProperties.class.getClassLoader();
//通过类加载器获取db.properties文件,并转换为输入流
InputStream is=classLoader.getResourceAsStream("db.properties");
Properties pt=new Properties();
pt.load(is);
url=pt.getProperty("url");
user=pt.getProperty("user");
password=pt.getProperty("password");
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取一个数据库连接对象
* @return
*/
public static Connection getConnection() {
try {
return DriverManager.getConnection(url,user,password);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 关闭连接
* @param rs
* @param ps
* @param con
*/
public static void close(ResultSet rs,PreparedStatement ps,Connection con) {
closeResultSet(rs);
closePreparedStatement(ps);
closeConnection(con);
}
/**
* 关闭结果集
* @param rs
*/
private static void closeResultSet(ResultSet rs) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭数据库预处理操作对象
* @param ps
*/
private static void closePreparedStatement(PreparedStatement ps) {
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭数据库连接
* @param con
*/
private static void closeConnection(Connection con) {
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
其中涉及到一个知识点,类加载器加载db.properties文件.
注意:要将db.properties文件加载到编码路径下才行.
创建一个config包,然后右键build path添加
//获取类加载器
ClassLoader classLoader = DBUtilProperties.class.getClassLoader();
//通过类加载器获取db.properties文件,并转换为输入流
InputStream is=classLoader.getResourceAsStream("db.properties");