一般我们也很少原生JDBC,都是在ORM框架上做二次开发,确实框架帮我们做了很多事情,但是原生JDBC我们还是需要掌握的,网上很多代码为了省事写的很不规范,很容易误导第一次接触的人JDBC的人,接下来我详细解释一下使用原生JDBC的每个步骤,以及规范的编写代码,以MySQL为例。
主要分为以下六个步骤:
1.加载数据库驱动
2.根据配置的信息(用户、密码等等)获取链接
3.根据链接获取向数据库发送SQL语句的statement对象
4.执行statement对象获取结果集对象
5.从结果集对象中获取数据
6.释放资源
下面开始详细说明每个步骤,具体的每个类的所有使用方法可以参照API文档
1.加载数据库驱动
毫无疑问,首先到导入jdbc的驱动jar包,把mysql-connector-java-commercial-5.1.25-bin.jar添加到依赖库当中,我的MySQL版本5.5。
下面就是正式的加载驱动,网上大致有三种写法:
导包如下
import com.mysql.jdbc.Driver;
import java.sql.DriverManager;
DriverManager.registerDriver(new Driver()); //方法一
new Driver(); //方法二
Class.forName("com.mysql.jdbc.Driver"); //方法三
这三种方法都可以将MySQL的驱动注册到DeiverManager当中,方法一最直接明了,显式的注册,其实我们可以打开驱动源码看看
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
也就是说,我们只要对这个驱动类进行初始化(静态代码块将执行)就可以了,他会自动注册到DriverManager中。所以方法一和方法二都无端new出了一个Driver对象,其实并不需要这个对象,又麻烦垃圾回收器再进行一次回收,所以方法三是最优的,Class.forName()将触发类加载的初始化过程。
2.根据配置的信息(用户、密码等等)获取链接
DriverManager manager = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdb", "root", "root");
这个信息写到配置文件当中更好,然后从配置文件当中读取,例如:
private static Properties dbConfig = new Properties();
static {
try {
dbConfig.load(JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"));
Class.forName(dbConfig.getProperty("driver"));
} catch (Exception e) {
throw new Error(e);
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(dbConfig.getProperty("url"), dbConfig.getProperty("username"),dbConfig.getProperty("password"));
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
3.根据链接获取向数据库发送SQL语句的statement对象
有两种获取statement对象的方式:
Statement state = conn.createStatement();
String id="1";
ResultSet set = state.executeQuery("select * from lab where id>"+id);
String sql = "select * from user where id>?";
PreparedStatement state = conn.prepareStatement(sql);
state.setLong(1, id);
ResultSet set = st.executeQuery();
第一个方法会引发SQL注入问题,而第二个方法对sql语句进行预编译,这样可以避免SQL注入问题,而且预编译好的sql语句数据库执行起来更快。
4.执行statement对象获取结果集对象
ResultSet set = state.executeQuery(); //查询操作执行该方法
int r = state.executeUpdate(); //增删改执行该方法
5.从结果集对象中获取数据
while(set.next()) {
System.out.println(set.getInt(2)+" "+set.getString("name"));
}
我们可以从列名或者第几列(下标从第1列开始,而不是第0列)来获取数据,每次next会将游标移到下一行数据,直到数据读取完 返回false,后面我会专门出一篇博客讲解如何用java获取MySQL的各种常用数据类型。
操作各种数据类型
6.释放资源
释放资源不只是要释放链接,还要释放statement对象和resultset对象,在finally里面按获取的相反顺序释放。
finally {
if (set != null) {
try {
set.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(state!=null) {
try {
state.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
resultset对象释放之后就无法继续从里面获取数据了,ResultSet依赖于当前的链接,它必须保持与数据库的连接(非离线),如果一定要传递ResultSet里面的数据,可以考虑在遍历ResultSet的时候获取需要的数据把数据封装进一个java对象中,转而传递这个java对象,这样便于传输、序列化(实现序列化接口)等等。
拓展学习 其实有个东西叫 RowSet [JAVA基础之RowSet]
下面是一个完整的例子,在一个类中展示了所有的步骤,但是你应该把一些代码抽取出来,比如:加载驱动和资源释放放入一个专门的类当中。
import com.mysql.jdbc.Driver;
import java.sql.*;
public class MainJDBC {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement state = null;
ResultSet set = null;
try {
//1.加载数据库驱动
DriverManager.registerDriver(new Driver());
//2.根据配置的信息(用户、密码等等)获取链接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdb", "root", "root");
//3.根据链接获取向数据库发送SQL语句的statement对象
state = conn.prepareStatement("select * from lab where id>?");
state.setInt(1, 1);
//4.执行statement对象获取结果集对象
set = state.executeQuery();
//5.从结果集对象中获取数据
while (set.next()) {
System.out.println(set.getInt(2) + " " + set.getString("name"));
}
//6.释放资源
} catch (Exception e) {
e.printStackTrace();
} finally {
if (set != null) {
try {
set.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (state != null) {
try {
state.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}