标签:
JDBC(Java Database Connection)是Java提供的数据库连接标准,具体的标准实现由各个数据库厂商提供。
下面以MySQL为例来简单演示JDBC接口的基本用法。
JDBC连接数据库的基本步骤如下:
1.加载要连接的数据库驱动,运用了反射机制。
加载MySQL驱动的代码为:Class.forName("com.mysql.jdbc.Driver");
2.通过DriverManager来获取与要连接的数据库的一个连接。
代码格式为:DriverManager.getConnection(c, "root", "1234");
其中字符串c为"jdbc:mysql://localhost:3306/databaseName?useUnicode=true&characterEncoding=utf8";
后面的字符串指定有可能对解决中文乱码问题有帮助,如果数据库默认编码支持中文也可以不设置。
以上两个步骤完成后就完成了数据库的连接,如果想要进一步对数据库操作,要根据不同的应用情景来实现。
1)通过Statement来获取并执行SQL语句。
缺点:容易造成SQL注入,对数据库造成安全隐患。但是在执行SQL批处理时可以很方便的使用。
下面代码可以体现其用法。
package com.wxisme.jdbc01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 连接MySQL基本流程
* @author wxisme
*
*/
public class Demo02 {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
//先加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理来建立连接
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
con = DriverManager.getConnection(c, "root", "1234");
//创建statement
String sql = "select * from student where b=‘张三‘";
stmt = con.createStatement();
//创建结果集 不能预编译SQL 只能在执行时传入SQL
rs = stmt.executeQuery(sql);
//next()指针指向下一条记录,如果有返回true,否则返回false
while(rs.next()) {
for(int i=1; i<10; i++) {
//getString()可以传入字段名,也可以传入字段的Index
System.out.print(rs.getString(i)+" ");
}
System.out.println();
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2)通过prepareStatement预编译SQL,防止SQL注入。
优点:可以防止SQL注入并预编译SQL可以提高效率,可以使用?占位符,写SQL语句时不用拼字符串,不容易出错。但是在批量处理时不方便使用。
public class Demo01 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
//先加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理来建立连接
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
con = DriverManager.getConnection(c, "root", "1234");
//创建statement
String sql = "select * from student where b=?";
stmt = con.prepareStatement(sql);
stmt.setString(1, "张三");
//创建结果集
rs = stmt.executeQuery();
while(rs.next()) {
for(int i=1; i<10; i++) {
System.out.print(rs.getString(i)+" ");
}
System.out.println();
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3)使用批处理一次提交执行批量SQL语句。
public class Demo03 {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
try {
//先加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理来建立连接
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
con = DriverManager.getConnection(c, "root", "1234");
con.setAutoCommit(false);//将连接的事务设为手动提交
//创建statement
stmt = con.createStatement();
for(int i=0; i<900000; i++) {
String sql = "insert into student (a,b,c) values(‘中文‘,‘刘琦‘,‘2013010‘)";
stmt.addBatch(sql);
}
stmt.executeBatch();
con.commit();//提交事务
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
4)数据库事务的提交和回滚,在默认情况下,数据库事务是自动提交的,但是如果手动提交,在最后调用数据库连接的回滚方法,在一个SQL语句有了错误抛出异常后,其他的SQL语句都不再执行,已经执行的SQL语句回滚到以前的状态,就是如果有异常抛出则数据库中的数据不会发生变化。
package com.wxisme.jdbc01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
/**
* 事务的手动提交和回滚
* @author wxisme
*
*/
public class Demo04 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement stmt = null;
try {
//先加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理来建立连接
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
con = DriverManager.getConnection(c, "root", "1234");
//创建statement
con.setAutoCommit(false);//设置为手动提交事务
String sql = "insert into student (?) values(?)";
stmt = con.prepareStatement(sql);
stmt.setString(1, "a");
stmt.setString(2, "刘琦");
con.commit();//手动提交事务
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
try {
con.rollback();//如果出现异常则回滚事务
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
5)对日期的支持,在java.sql包中有Date,Time,Timestamp类来支持时间和日期的处理。
package com.wxisme.jdbc01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Random;
/**
* 时间处理java.sql.Date,Time,Timestamp
* 插入带有日期和时间戳类型字段的记录
* @author wxisme
*
*/
public class Demo05 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
//加载驱动类
Class.forName("com.mysql.jdbc.Driver");
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
conn = DriverManager.getConnection(c, "root", "1234");
for(int i=0;i<1000;i++){
ps = conn.prepareStatement("insert into student (name,pswd,time,stime) values (?,?,?,?)");
ps.setObject(1, "流苏款"+i);
ps.setObject(2, "123456");
int rand = 100000000+new Random().nextInt(1000000000);
java.sql.Date date = new java.sql.Date(System.currentTimeMillis()-rand);
Timestamp stamp = new Timestamp(System.currentTimeMillis()-rand); //如果需要插入指定日期,可以使用Calendar、DateFormat
ps.setDate(3, date);
ps.setTimestamp(4, stamp);
ps.execute();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(ps!=null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package com.wxisme.jdbc01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 时间处理java.sql.Date,Time,Timestamp
* 查找某个时间段的记录
* @author wxisme
*
*/
public class Demo06 {
/**
* 将字符串代表的日期转为long数字(格式:yyyy-MM-dd hh:mm:ss)
* @param dateStr
* @return
*/
public static long str2Date(String date) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
return format.parse(date).getTime();
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//加载驱动类
Class.forName("com.mysql.jdbc.Driver");
String c = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8";
conn = DriverManager.getConnection(c, "root", "1234");
ps = conn.prepareStatement("select * from student where stime>? and stime<? order by stime ");
Timestamp start = new Timestamp(str2Date("2015-5-1 8:10:20"));
Timestamp end = new Timestamp(str2Date("2015-5-1 9:9:10"));
ps.setObject(1, start);
ps.setObject(2, end);
rs = ps.executeQuery();
while(rs.next()){
System.out.println(rs.getString("name")+"--"+rs.getTime("time")+"--"+rs.getTimestamp("stime"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(ps!=null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
总结:JDBC把数据库连接封装的很好,总的步骤是固定的,写几个Demo之后就熟悉了,但是在数据库连接时要注意很多细节问题,代码写的严谨才不会出BUG。
标签:
原文地址:http://www.cnblogs.com/wxisme/p/4502210.html