jdbc使用分析
Posted 九死九歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdbc使用分析相关的知识,希望对你有一定的参考价值。
JDBC,全称Java Database Connectivity,就是说你操作数据库,要么自己手动写,要么用java的jdbc框架自动化操作数据库。
另外java.sql包里面几乎全都是接口,没有实现类。实现类几乎都是各个数据库开发公司整的外部库。我们这里用的是mysql的jdbc外部库。
一、建立java与MySQL的连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* <p>测试与数据库建立连接</p>
* @author 九死九歌
*/
public class Demo01 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try {
/*建立连接*/
/*建立连接的过程中内部包含了Socket对象,所以比较耗时!这是Connection对象管理的一个特点*/
/*真正做开发时都会选择用连接池来连接对象*/
Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
System.out.println(con);
con.close();
} catch (SQLException e) {
System.err.println("sql语句有问题");
e.printStackTrace();
}
}
}
二、利用Statement执行MySQL语句
实际上Statement PreparedStatement CallableStatement都可以执行MySQL语句,并且第一个是后两个的父类。较为常用的是第二种,第三种几乎不用,我这里也就只说前两种。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 测试用Statement执行sql语句以及sql注入问题
* @author 孙培迪
*/
public class Demo02 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
Statement stmt = con.createStatement()) {
/* Statement不常用,因为他执行语句要自己拼字符串 */
/* 一旦字符串是拼起来的,那就容易发生SQL注入,被人家攻击你的库 */
String name = "宋浩";
int pwd = 123456;
String sql = "insert into t_user (username, pwd, regTime) values ('"
+name+"', "+pwd+", now())";
stmt.execute(sql);
/* 所以实际开发的过程中使用的都是PreparedStatement,即预编译的Statement */
} catch (SQLException e) {
System.err.println("sql语句有问题");
e.printStackTrace();
}
}
}
三、利用PreparedStatement执行MySQL语句
这个比上面那个更常用。
import java.sql.*;
/**
* <p>测试PreparedStatement</p>
* @author 九死九歌
*/
public class Demo03 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
String sql = "insert into t_user (username, pwd, regTime) values (?, ?, ?)"; // ?叫做占位符
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps = con.prepareStatement(sql)) {
// ps.setString(1, "汤家凤"); // 参数索引要从1开始
// ps.setString(2, "123456");
/* 也可以用setObject,完全不用管类型。 */
ps.setObject(1, "汤家凤");
ps.setObject(2, "123456");
/* 这里可以setDate,当然也可以setObject */
// ps.setDate(3, new Date(System.currentTimeMillis()));
ps.setObject(3, new Date(System.currentTimeMillis()));
ps.execute();
} catch (SQLException e) {
System.err.println("sql语句有问题");
e.printStackTrace();
}
}
}
四、探究ResultSet结果集和PreparedStatement的executeQuery()
import java.sql.*;
/**
* <p>测试ResultSet结果集的基本用法</p>
* @author九死九歌
*/
public class Demo04 {
/* con ps 和 rs 可以试着用try-with-resource */
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
String sql = "select id, username, pwd from t_user where id>?"; // ?叫做占位符
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setObject(1, 1);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.print(rs.getInt(1));
System.out.print("|" + rs.getString(2));
System.out.println("|" + rs.getString(3));
}
} catch (SQLException e) {
System.err.println("sql语句有问题");
e.printStackTrace();
}
}
}
五、Batch批处理
对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,当数据量特别大时,会发生异常。
package com.spd.jdbc;
import java.sql.*;
/**
* <p>测试批处理的基本方法</p><br/>
* <p>对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,当数据量特别大时,会发生异常。(不要叫我复读机)<p/>
* @author 九死九歌
*/
public class Demo05 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
Statement stmt = con.createStatement();) {
con.setAutoCommit(false); // 设置为事物手动提交(false)
for (int i = 0; i < 1000; i++) {
stmt.addBatch("insert into t_user(username, pwd, regTime) values ('僵尸粉"+(i+1)+"', '123456', now())");
}
stmt.executeBatch(); // 进行批处理
con.commit(); // 提交事务
}catch (SQLException e) {
System.err.println("sql语句有问题");
e.printStackTrace();
}
}
}
六、事务
1.概念:
一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元!
2.事务开始于:
- 连接到数据库上,并执行条DML语句(INSERT、 UPDATE或DELETE)。
- 前一个事务结束后,又输入了另外一条DML语句。
3.事务结束于:
- 执行COMMI或ROLL BACK语句。
- 执行一条DDL语句 ,例如CREATE TABLE语句;在这种情况下,会自动执行COMMIT语句。
- 执行一条DCL语句,例如GRANT语句;在这种情况下,会自动执行
COMMIT语句。 - 断开与数据库的连接。
- 执行了一条DML语句,该语句却失败了;在这种情况中,会为这个无效的
DML语句执行ROLLBACK语句。
4.事务的四大特点(ACID):
- atomicity(原子性)
- 表示一一个事务内的所有操作是一个整体,要么全部成功,要么全失败;
- consistency(一致性)
- 表示一一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前的状态。
- isolation(隔离性)
- 事务查看数据时数据所处的状态,要么是另一-并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
- durability(持久性)
- 持久性事务完成之后,它对于系统的影响是永久性的。
(隔离性相当于对数据库加上了一个sychronized属性)
5.事务隔离级别由高到低:
- 读取未提交(read uncommitted)
- 读取已提交(read committed)
- 可重复读(repeatable read)
- 序列化(serializable)
越往下隔离性越低效率越低,sychronized程度越高,一般用的都是第二种读取已提交。
import java.sql.*;
/**
* <p>测试事务的基本概念和用法</p>
* @author 九死九歌
*/
public class Demo06 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps1 = con.prepareStatement
("insert into t_user (username, pwd) values (?, ?)");
PreparedStatement ps2 = con.prepareStatement
("insert into t_user (username, pwd) values (?, ?, ?)");) {
con.setAutoCommit(false); // jdbc中默认事务自动提交(true),所以要手动改成false
ps1.setObject(1, "二次元刀酱-刀哥");
ps1.setObject(2, "louniuzhile");
ps1.execute();
System.out.println("网络世界真真假假,妹有人是不怕屎滴");
try {
Thread.sleep(5000);
} catch (InterruptedException ignored){}
ps2.setObject(1, "东北虎哥");
ps2.setObject(2, "woshigesanbing");
ps2.execute();
System.out.println("我徒弟呢?我徒弟!那是我徒弟!杀马特团长我跟你没完~~~");
/* 这俩要成功同时成功,要失败同时失败,所以即便ps1没问题,有问题的是ps2,仍然是两个都无法执行。 */
con.commit();
} catch (SQLException e) {
System.err.println("SQL语法出现异常");
e.printStackTrace();
}
}
}
七、jdbc的时间处理
sql包用于事件处理的类有三个,这三个都继承自util包的Date
- Date:表示年月日
- Time:表示时分秒
- TimeStamp:表示年月日时分秒
1.利用System.currentTimeMillis()插入当前时间
import java.sql.*;
/**
* <p>测试事件的处理(java.sql.Date Time TimeStamp)</p>
* @author 九死九歌
*/
public class Demo07 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps = con.prepareStatement
("insert into t_user (username, pwd, regTime, logTime) values (?, ?, ?, ?)");) {
ps.setObject(1, "徒步阿龙");
ps.setObject(2, "xingfuankang");
/* 利用sql包的Date类(注意:这个可不是utils包的) */
Date date = new Date(System.currentTimeMillis());
ps.setDate(3, date);
/* 同为sql包的TimeStamp类 */
Timestamp stamp = new Timestamp(System.currentTimeMillis()); // 如果要插入指定日期,可以使用Calendar、DateFormat
ps.setTimestamp(4, stamp);
ps.execute();
System.out.println("我害怕鬼,但是鬼未伤我分毫\\n我不害怕人,但是人把我害得 遍 体 鳞 伤");
} catch (SQLException e) {
System.err.println("SQL语法出现异常");
e.printStackTrace();
}
}
}
2.随机插入时间
import java.sql.*;
/**
* <p>测试事件的处理(java.sql.Date Time TimeStamp)</p>
* @author 九死九歌
*/
public class Demo07 {
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps = con.prepareStatement
("insert into t_user (username, pwd, regTime, logTime) values (?, ?, ?, ?)");) {
for (int i = 0; i < 100; i++) {
ps.setObject(1, "徒步阿龙" + i + "号");
ps.setObject(2, "xingfuankang");
long n = (long) Math.ceil(1000000000L * Math.random());
n %= 1000000000L;
n -= 1000000000L /2;
/* 利用sql包的Date类(注意:这个可不是utils包的) */
Date date = new Date(System.currentTimeMillis()-n);
ps.setDate(3, date);
/* 同为sql包的TimeStamp类 */
Timestamp stamp = new Timestamp(System.currentTimeMillis()-n); // 如果要插入指定日期,可以使用Calendar、DateFormat
ps.setTimestamp(4, stamp);
ps.execute();
}
System.out.println("我害怕鬼,但是鬼未伤我分毫\\n我不害怕人,但是人把我害得 遍 体 鳞 伤");
} catch (SQLException e) {
System.err.println("SQL语法出现异常");
e.printStackTrace();
}
}
}
3.对时间段进行数据查询
import java.sql.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
*
* <p>测试事件的处理(java.sql.Date Time TimeStamp)</p><br/>
* <i>取出指定时间段的</i><b>数据<b/>
* @author 九死九歌
*/
public class Demo08 {
/**
* <p>将字符串代表的时间转化成长整形</p>
* (格式为yyyy-mm-dd hh:mm:ss)
* @param str
* @return
*/
public static long stringToDate(String str) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
return format.parse(str).getTime();
} catch (ParseException e) {
return -1;
}
}
public static void main(String[] args) {
/*加载驱动类*/
try {
Class cls = Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("未找到驱动类!");
}
ResultSet rs = null;
try(Connection con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/testjdbc", "root", "root");
PreparedStatement ps = con.prepareStatement
("select * from t_user where regTime>? and regTime<?");) {
Date start = new Date(stringToDate("2021-6-20 00:00:00"));
Date end = new Date(stringToDate("2021-6-30 00:00:00"));
ps.setDate(1, start);
ps.setDate(2, end);
rs 以上是关于jdbc使用分析的主要内容,如果未能解决你的问题,请参考以下文章
关于mysql驱动版本报错解决,Cause: com.mysql.jdbc.exceptions.jdbc4Unknown system variable ‘query_cache_size(代码片段
SpringBoot - 05. 数据访问之JDBC(源码分析+代码下载)
使用Java代码通过JDBC连接只启用Sentry的Impala异常分析
Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段