Java基础-面向接口编程-JDBC详解
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.JDBC概念和数据库驱动程序
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范。本篇博客使用的介绍的是Java链接MySQL数据库,如果对MySQL数据不是很了解的小伙伴请参考:http://www.cnblogs.com/yinzhengjie/p/9011342.html
JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
本篇博客使用的是mysql的驱动mysql-connector-java-5.1.39-bin.jar,若没有安装包请自行下载,若在网上没有找到相应的解决方案,别担心,我已经帮你把坑踩好了,请参考:http://www.cnblogs.com/yinzhengjie/p/9017416.html
二.JDBC原理
Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。
三.JDBC的开发步骤
1>.JDBC操作数据库的步骤
a>.注册驱动
告知JVM使用的是哪一个数据库的驱动。
b>.获得链接
使用JDBC中的类,完成对MySQL数据库的链接。
c>.获得语句执行平台
通过链接对象获取对SQL语句的执行者对象。
d>.执行SQL语句
使用执行者对象,向数据库执行SQL语句,获取到数据库执行后的结果。
e>.处理结果
就是我们当我们拿到数据库执行后的结果想要完成的业务逻辑。
f>.释放资源
关闭网络链接,跟IO流类似,调用其close方法即可。
2>.导入MySQL数据库驱动程序jar包
a>.在当前项目下,创建lib目录,在lib目录下创建MySQL目录(用于标识该目录只存放MySQL相关驱动),并将下载的好的按照保导入该文件夹中。
b>.将下载后的Java包添加到项目中的环境变量中
c>.导入MySQL驱动成功标志
3>.准备数据库数据(我开发环境在虚拟机上安装的,真正的MySQL服务安装在宿主机上,模拟的是生产环境中链接服务器)
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/
EMAIL:y1053419035@qq.com
*/ #创建表结构
create table Classmate(
ID int(11) NOT NULL primary key AUTO_INCREMENT,
Name varchar(30) COLLATE gbk_bin DEFAULT NULL,
Age int DEFAULT NULL,
Job varchar(50),
Chinese int,
English int,
Math int,
Physics int,
Chemistry int,
Biology int
); #往表里添加数据
insert into Classmate values(null,'王建军',30,'Java讲师',100,98,99,96,97,100);
insert into Classmate values(null,'常庆林',28,'Linux讲师',100,100,98,93,99,96);
insert into Classmate values(null,'徐培成',35,'BigData讲师',100,100,100,98,96,100);
insert into Classmate values(null,'李永强',30,'javaEE开发工程师',100,93,91,74,89,100);
insert into Classmate values(null,'赵子昂',24,'python开发工程师',98,93,91,74,89,100);
insert into Classmate values(null,'桂阳',25,'C++开发工程师',100,98,93,91,99,82);
insert into Classmate values(null,'肖云龙',24,'Golang开发工程师',93,97,85,100,93,69);
insert into Classmate values(null,'李洋',23,'C#开发工程师',100,98,99,96,97,100);
insert into Classmate values(null,'卜孟龙',30,'BigData开发',98,93,100,100,73,92);
insert into Classmate values(null,'罗大鹏',22,'Java开发工程师',100,84,91,87,100,93);
insert into Classmate values(null,'尹正杰',26,'高级运维工程师',100,100,100,100,100,100);
四.JDBC执行insert语句( Statement接口的实现类对象)
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement; public class JDBCDemo { public static void main(String[] args) throws Exception { //1.注册驱动,利用java反射技术,将驱动类加入到内容
/*使用java.sql.DriverManager类静态方法 registerDriver(Driver driver)
Diver是一个接口,参数传递,MySQL驱动程序中的实现类
DriverManager.registerDriver(new Driver());
驱动类源代码,注册2次驱动程序 */
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库连接 DriverManager类中静态方法
/*static Connection getConnection(String url, String user, String password)
返回值是Connection接口的实现类,在mysql驱动程序
url: 数据库地址 jdbc:mysql://连接主机IP:端口号//数据库名字 */
String url = "jdbc:mysql://192.168.0.254:5200/yinzhengjie";
String username="root";
String password="yinzhengjie";
Connection conn = DriverManager.getConnection(url, username, password);
//3.获得语句执行平台, 通过数据库连接对象,获取到SQL语句的执行者对象
/* conn对象调用方法 Statement createStatement() 获取Statement对象,将SQL语句发送到数据库返回值是 Statement接口的实现类对象.*/
Statement stat = conn.createStatement();
// 4.执行sql语句
/* 通过执行者对象调用方法执行SQL语句,获取结果 int executeUpdate(String sql) 执行数据库中的SQL语句, insert,delete,update操作,返回值int,操作成功数据表多少行 */
String sql = "insert into Classmate values(null,'邓西',27,'DBA开发工程师',98,100,81,70,100,90);";
int row = stat.executeUpdate(sql);
System.out.printf("表中有【%d】行发生了改变!",row);
//6.释放资源 一堆close()
stat.close();
conn.close();
}
} /*
以上代码执行结果如下:
表中有【1】行发生了改变!
*/
五.JDBC执行select语句(ResultSet接口的实现类)
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/*
* JDBC技术,查询数据表,获取结果集
*/
public class JDBCDemo1 {
public static void main(String[] args) throws Exception{
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://192.168.0.254:5200/yinzhengjie";
String username="root";
String password="yinzhengjie";
Connection conn = DriverManager.getConnection(url, username, password);
//3 .获取执行SQL 语句对象
Statement stat = conn.createStatement();
// 拼写查询的SQL
String sql = "select * from classmate";
//4. 调用执行者对象方法,执行SQL语句获取结果集
/* ResultSet executeQuery(String sql) 执行SQL语句中的select查询,返回值ResultSet接口的实现类对象,实现类在mysql驱动中*/
ResultSet rs = stat.executeQuery(sql);
//5 .处理结果集
// ResultSet接口方法 boolean next() 返回true,有结果集,返回false没有结果集
//获取结果集中的数据,一种是逐行获取每列的内容,如果知道是字符串就用getString方法接住,类型为String,如果知道是数字则用getInt方式接着,类型为int,如果你不知道此列的类型可以用getObject接住,类型为Object。
/*根据每列的长度进行取值,不推荐使用
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
String job = rs.getString(4);
int Chinese = rs.getInt(5);
int English = rs.getInt(6);
int Math = rs.getInt(7);
int Physics = rs.getInt(8);
int Chemistry = rs.getInt(9);
int Biology = rs.getInt(10);
System.out.println(id +","+ name +","+ age +","+ job +","+ Chinese+","+ English+","+ Math+","+ Physics+","+ Chemistry+","+ Biology);
}*/
//除了上面的取值方式,当然还可以用列明的方式取值啦。这样你可以清楚的知道自己取出来的是什么数据,推荐使用该方法。
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String job = rs.getString("job");
int Chinese = rs.getInt("Chinese");
int English = rs.getInt("English");
int Math = rs.getInt("Math");
int Physics = rs.getInt("Physics");
int Chemistry = rs.getInt("Chemistry");
int Biology = rs.getInt("Biology");
System.out.println(id +","+ name +","+ age +","+ job +","+ Chinese+","+ English+","+ Math+","+ Physics+","+ Chemistry+","+ Biology);
}
//6.释放资源 一堆close()
rs.close();
stat.close();
conn.close();
}
} /*
以上代码执行结果如下:
1,王建军,30,Java讲师,100,98,99,96,97,100
2,常庆林,28,Linux讲师,100,100,98,93,99,96
3,徐培成,35,BigData讲师,100,100,100,98,96,100
4,李永强,30,javaEE开发工程师,100,93,91,74,89,100
5,赵子昂,24,python开发工程师,98,93,91,74,89,100
6,桂阳,25,C++开发工程师,100,98,93,91,99,82
7,肖云龙,24,Golang开发工程师,93,97,85,100,93,69
8,李洋,23,C#开发工程师,100,98,99,96,97,100
9,卜孟龙,30,BigData开发,98,93,100,100,73,92
10,罗大鹏,22,Java开发工程师,100,84,91,87,100,93
11,尹正杰,26,高级运维工程师,100,100,100,100,100,100
12,邓西,27,DBA开发工程师,98,100,81,70,100,90
*/
六.Java防SQL注入的解决方案
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement; /*
*
* 1.statement使用的不方便
* 2.sql注入的问题
* 在SQL语句中使用了系统自带的关键字 or and ,让where条件判断失效
*
* prepareStatement:
* 1.sql语句不用在拼字符串
* 2.防止sql注入问题
*
*/
public class CURDDemo { public static void main(String[] args) throws Exception {
// insertTest();
insertTest2(); //优化后的代码
// deleteTest();
// deleteTest2(); //优化后的代码
} // 删除方法,存在SQL注入风险!
private static void deleteTest() throws Exception {
Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.254:5200/yinzhengjie", "root", "yinzhengjie"); Statement st = conn.createStatement(); int id = 4;
//定义我们想要执行的语句
// String sql = "delete from emp where eid = " + id ";
//一些对SQL语句小朋友喜欢搞点事情,把上面的代码添头加醋,就生成了以下代码(" or 1 = 1"),最终会导致where匹配条件失效,导致清空掉了整个数据库内容!是不是有点小惊讶呢?
String sql = "delete from classmate where id = " + id + " or 1 = 1";
//除了上面说的SQL注入情况外,按照上面的拼接字符串真的让人欲哭无泪啊,庆幸的是我上面测试环境参数相对较少,要是在实际生产环境中就有50个参数要传递那只要你的小手一哆嗦就很容易出错呢!
int i = st.executeUpdate(sql); if (i != 0) {
System.out.println("删除成功");
} st.close();
conn.close();
} // 删除优化,解决掉SQL注入风险以及拼接字符串的烦恼!
private static void deleteTest2() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.254:5200/yinzhengjie", "root", "yinzhengjie");
/*调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类,方法中参数,SQL语句中的参数全部采用问号占位符*/
String sql = "delete from classmate where id = ?";
PreparedStatement pst = conn.prepareStatement(sql);
//我们在传参数的时候
// pst.setInt(1, 12);
//这个时候我们再去模仿SQL注入,发现数据库真实删除的只有第二条。关于后面的“or 1 = 1”压根就没有执行!!,是不是很高大上?
pst.setString(1," 2 or 1 = 1" );
int i = pst.executeUpdate(); if (i != 0) {
System.out.println("删除成功");
} pst.close();
conn.close();
} // 增,也能存在SQL注入的风险,不推荐使用!
private static void insertTest() throws Exception {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.254:5200/yinzhengjie", "root", "yinzhengjie");
// 创建statement对象
Statement st = conn.createStatement();
// 执行sql语句
// 真实场景中,sql中的数据都是从外界获取的. String name = "方合意";
int age = 21;
String job = "Python开发工程师";
int chinese = 100;
int english = 89;
int math = 98;
int physics = 91;
int chemistry = 73;
int biology = 89; String sql = "insert into classmate values(null,'" + name + "', " + age + ", '" + job+ "', " + chinese+ ", " + english+ ", " + math + ", " + physics + ", " + chemistry +", " + biology+ ")"; int i = st.executeUpdate(sql);
// 判断插入语句是否执行成功
if (i != 0) {
System.out.println("插入数据成功");
}
st.close();
conn.close();
} //增,防止SQL注入版本!
private static void insertTest2() throws Exception {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver"); // 获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.254:5200/yinzhengjie", "root", "yinzhengjie");
/*调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类,方法中参数,SQL语句中的参数全部采用问号占位符*/
String sql = "insert into classmate values (null,?,?,?,?,?,?,?,?,?)"; PreparedStatement pst = conn.prepareStatement(sql);
//调用pst对象set方法,设置问号占位符上的参数
pst.setString(1, "邓聪");
pst.setInt(2, 28);
pst.setString(3, "网络工程师");
pst.setInt(4, 100);
pst.setInt(5, 98);
pst.setInt(6, 89);
pst.setInt(7, 86);
pst.setInt(8, 97);
pst.setInt(9, 94); int i = pst.executeUpdate();
// 判断插入语句是否执行成功
if (i != 0) {
System.out.println("插入数据成功");
} pst.close();
conn.close(); }
} /*
以上代码执行结果如下:
插入数据成功
*/
八.JDBC的工具类和测试
DriverName=com.mysql.jdbc.Driver
#zai "url" lu jing hou jia "?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true" ke yi kai qi pi chu li mo shi !
url=jdbc:mysql://192.168.0.254:5200/yinzhengjie?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
user=root
password=yinzhengjie
config.properties 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note1; import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties; /*
* 获取数据库连接的工具类
* 在获取连接对象的方法中,首先是注册驱动,实际上没有必要
* 注册驱动只需要执行一次就OK
*
*/
public class Utils { private Utils(){} private static Properties p = new Properties();
private static String driver;
private static String url;
private static String user;
private static String password; //加载配置文件
static{
try {
// p.load(Utils.class.getClassLoader().getResourceAsStream("config.properties"));
p.load(new FileInputStream("config.properties"));
driver = p.getProperty("DriverName");
url = p.getProperty("url");
user = p.getProperty("user");
password = p.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
} //注册驱动
static{
//注册驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static Connection getConnect() throws Exception{
//获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} }
Utils.java 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note1; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test; public class Demo {
@Test //注意,这个Test是单元测试,程序员不需要写main方法就可以测试!选中方法名运行即可。
public void insertTest() throws Exception{
//使用工具类获取连接
Connection conn = Utils.getConnect(); // 创建statement对象
Statement st = conn.createStatement(); // 执行sql语句
String sql = "insert into Classmate values(null,'陶涛',22,'网络工程师',100,100,72,93,79,81)";
int i = st.executeUpdate(sql);
// 判断插入语句是否执行成功
if (i != 0) {
System.out.println("插入数据成功");
} st.close();
conn.close();
} @Test //注意,这个Test是单元测试,程序员不需要写main方法就可以测试!选中方法名运行即可。
public void deleteTest() throws Exception{
Connection conn = Utils.getConnect(); Statement st = conn.createStatement();
String name = "陶涛";
//注意,字段需要用单引号引起来,这是数据库的语法规则!因此我们需要在字符串两侧加上相应的单引号!
String sql = "delete from classmate where name = '" + name + "'"; int i = st.executeUpdate(sql); if (i != 0) {
System.out.println("删除成功");
} st.close();
conn.close();
} @Test //注意,这个Test是单元测试,程序员不需要写main方法就可以测试!选中方法名运行即可。
public void updateTest() throws Exception{ Connection conn = Utils.getConnect(); Statement st = conn.createStatement(); String sql = "update classmate set English = English + 120";
int i = st.executeUpdate(sql); if (i != 0) {
System.out.println("修改成功");
} st.close();
conn.close();
} @Test //注意,这个Test是单元测试,程序员不需要写main方法就可以测试!选中方法名运行即可。
public void selectTest() throws Exception{
Connection conn = Utils.getConnect();
Statement st = conn.createStatement(); String sql = "select * from classmate where id = 11"; //执行查询语句!
ResultSet rs = st.executeQuery(sql); while(rs.next()){
//如果你不知道返回值是什么类型的话,可以用getObject来接住哟!!!
Object id = rs.getObject("id");
Object name = rs.getObject("name");
Object age = rs.getObject("age");
Object job = rs.getObject("job");
Object chinese = rs.getObject("chinese");
Object english = rs.getObject("english");
Object math = rs.getObject("math");
Object physics = rs.getObject("physics");
Object chemistry = rs.getObject("chemistry");
Object biology = rs.getObject("biology");
System.out.println(id +","+ name +","+ age +","+ job+","+ chinese +","+ english +","+ math +","+ physics +","+ chemistry +","+biology);
} rs.close();
st.close();
conn.close();
} }
九.JDBC的异常处理
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement; public class ExceptionDemo { public static void main(String[] args) {
//提升作用域
Connection conn = null;
Statement st = null; try {
Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://192.168.0.254:5200/yinzhengjie", "root", "yinzhengjie"); String sql = "insert into classmate values (null,?,?,?,?,?,?,?,?,?)"; PreparedStatement pst = conn.prepareStatement(sql); pst.setString(1, "杨明明");
pst.setInt(2, 32);
pst.setString(3, "网络工程师");
pst.setInt(4, 100);
pst.setInt(5, 98);
pst.setInt(6, 89);
pst.setInt(7, 86);
pst.setInt(8, 97);
pst.setInt(9, 94); int i = pst.executeUpdate();
// 判断插入语句是否执行成功
if (i != 0) {
System.out.println("插入数据成功");
} } catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//对被关闭的对象进行非空判断
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
} }
} /*
以上代码执行结果如下:
插入数据成功
*/
十. JDBC操作较大数据对象
如果存储的对象较大,我们可以采用以二进流的方式存储,即BLOB,如果你较大的文本文件的话也可以采用TEXT进行存储。值得一说的是,在测试建表的时候要注意字段的数据类型, 如果类型指定的过小的话可能导致数据存储会失败哟!
1>.准备实验环境
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/
EMAIL:y1053419035@qq.com
*/ CREATE TABLE myblob(
id INT PRIMARY KEY AUTO_INCREMENT,
img LONGBLOB
); CREATE TABLE mytext(
id INT PRIMARY KEY AUTO_INCREMENT,
txt LONGBLOB
);
2>.JDBC操作BLOB对象
DriverName=com.mysql.jdbc.Driver
#zai "url" lu jing hou jia "?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true" ke yi kai qi pi chu li mo shi !
url=jdbc:mysql://192.168.0.254:5200/yinzhengjie?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
user=root
password=yinzhengjie
config.properties 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ResourceBundle; /*
* 获取数据库连接的工具类
* 在获取连接对象的方法中,首先是注册驱动,实际上没有必要
* 注册驱动只需要执行一次就OK
*
*/
public class Utils { private Utils(){} private static final String DRIVERCLASS;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
//使用配置文件
static {
//注意,这里写文件名的时候不要写全称,我们此处这需要写前缀就好,在Windows操作系统中如果你画蛇添足写上了文件名后缀可能会报错哟!
DRIVERCLASS = ResourceBundle.getBundle("config").getString("DriverName");
URL = ResourceBundle.getBundle("config").getString("url");
USERNAME = ResourceBundle.getBundle("config").getString("user");
PASSWORD = ResourceBundle.getBundle("config").getString("password");
} //注册驱动
static{
//注册驱动
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static Connection getConnect() throws Exception{ //获取连接
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return conn;
} }
Utils.java 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.note; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class BlobDemo { public static void main(String[] args) throws Exception {
// sava();
get();
} //获取二进制大对象
private static void get() throws Exception {
Connection conn = Utils.getConnect();
String sql = "select img from myblob where id = 1";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if(rs.next()){
InputStream in = rs.getBinaryStream(1);
FileOutputStream fos = new FileOutputStream("1.jpg");
byte[] buf = new byte[4096];
int len;
while((len = in.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
in.close();
}
rs.close();
ps.close();
conn.close();
} //保存二进制流文件到数据库
private static void sava() throws Exception, SQLException, FileNotFoundException {
Connection conn = Utils.getConnect();
String sql = "insert into myblob values(null,?)"; PreparedStatement ps = conn.prepareStatement(sql);
// ps.setBinaryStream(1, new FileInputStream("c:/dog.jpg")); //MySQL对这种方式传参不感冒!但是提供了其他方法进行传值!
File file = new File("C:/Users/yinzhengjie/Desktop/电子相册/1.jpg");
FileInputStream fis = new FileInputStream(file);
//将图片保存到数据库服务器中!
ps.setBinaryStream(1, fis, (int)file.length()); int i = ps.executeUpdate();
System.out.println(i); ps.close();
conn.close();
}
} /*
注意,如果出现以下报错的话,说明你上传的数据大于数据库定义的数据类型了哟!解决方法要么就是上传数据库规定的大小范围,要么修改数据库字段类型的限制范围。
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'img' at row 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2983)*/
3>.JDBC操作TEXT对象
DriverName=com.mysql.jdbc.Driver
#zai "url" lu jing hou jia "?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true" ke yi kai qi pi chu li mo shi !
url=jdbc:mysql://192.168.0.254:5200/yinzhengjie?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
user=root
password=yinzhengjie
config.properties 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ResourceBundle; /*
* 获取数据库连接的工具类
* 在获取连接对象的方法中,首先是注册驱动,实际上没有必要
* 注册驱动只需要执行一次就OK
*
*/
public class Utils { private Utils(){} private static final String DRIVERCLASS;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
//使用配置文件
static {
//注意,这里写文件名的时候不要写全称,我们此处这需要写前缀就好,在Windows操作系统中如果你画蛇添足写上了文件名后缀可能会报错哟!
DRIVERCLASS = ResourceBundle.getBundle("config").getString("DriverName");
URL = ResourceBundle.getBundle("config").getString("url");
USERNAME = ResourceBundle.getBundle("config").getString("user");
PASSWORD = ResourceBundle.getBundle("config").getString("password");
} //注册驱动
static{
//注册驱动
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static Connection getConnect() throws Exception{ //获取连接
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return conn;
} }
Utils.java 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; public class TextDemo { public static void main(String[] args) throws Exception {
// textSava();
textGet();
} private static void textGet() throws Exception {
Connection conn = Utils.getConnect();
String sql = "select txt from mytext where id = 1";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if(rs.next()){
InputStream in = rs.getBinaryStream(1);
FileOutputStream fos = new FileOutputStream("1.txt");
byte[] buf = new byte[4096];
int len;
while((len = in.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
in.close();
}
rs.close();
ps.close();
conn.close();
} private static void textSava() throws Exception {
Connection conn = Utils.getConnect();
String sql = "insert into mytext values(null,?)"; PreparedStatement ps = conn.prepareStatement(sql);
File file = new File("C:/Users/yinzhengjie/Desktop/Java常见的关键字.txt");
FileInputStream fis = new FileInputStream(file);
//将图片保存到数据库服务器中!
ps.setBinaryStream(1, fis, (int)file.length()); int i = ps.executeUpdate();
System.out.println(i); ps.close();
conn.close(); } }
十一.JDBC批处理案例
1>.准备实验环境
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/
EMAIL:y1053419035@qq.com
*/ CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT,
num int
);
2>.批处理操作
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/
EMAIL:y1053419035@qq.com
*/ CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT,
num int
);
config.propreties 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/ package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ResourceBundle; /*
* 获取数据库连接的工具类
* 在获取连接对象的方法中,首先是注册驱动,实际上没有必要
* 注册驱动只需要执行一次就OK
*
*/
public class Utils { private Utils(){} private static final String DRIVERCLASS;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
//使用配置文件
static {
//注意,这里写文件名的时候不要写全称,我们此处这需要写前缀就好,在Windows操作系统中如果你画蛇添足写上了文件名后缀可能会报错哟!
DRIVERCLASS = ResourceBundle.getBundle("config").getString("DriverName");
URL = ResourceBundle.getBundle("config").getString("url");
USERNAME = ResourceBundle.getBundle("config").getString("user");
PASSWORD = ResourceBundle.getBundle("config").getString("password");
} //注册驱动
static{
//注册驱动
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static Connection getConnect() throws Exception{ //获取连接
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return conn;
} }
Utils.java 文件内容
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.note; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement; /*
* 1.驱动版本5.1.13以上
* 2.在url中开启批处理功能
*/
public class BatchTest { public static void main(String[] args) throws Exception {
test1(); //3526毫秒
// test2(); //用时1523毫秒
} //5.1.13之后批处理功能,SQL语句的整体框架变动起来很方便!
private static void test1() throws Exception, SQLException {
Connection conn = Utils.getConnect();
Statement st = conn.createStatement();
long start = System.currentTimeMillis();
for(int i = 0;i<100000;i++){
String sql = "insert into test1 values(null," + i + ")";
st.addBatch(sql);
} st.executeBatch();
st.clearBatch();
st.close();
conn.close();
System.out.println(System.currentTimeMillis() - start);
} //SQL语句的整体框架变动起来麻烦,需要逐个进行预编译
private static void test2() throws Exception, SQLException {
Connection conn = Utils.getConnect();
String sql = "insert into test1 values(null,?)";
PreparedStatement ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis(); for(int i = 1;i<=100000;i++){
ps.setInt(1, i);
if(i % 1000 == 0){
ps.executeBatch();
ps.clearBatch();
}
ps.addBatch();
} ps.executeBatch();
ps.clearBatch();
ps.close();
conn.close();
System.out.println(System.currentTimeMillis() - start);
} }