JDBC全称是Java DataBase Connectivity,即Java数据库连接,它是一种可以执行SQL语句的Java API。
Java API是接口,其实现类由各数据库厂商提供实现,这些实现类就是“驱动程序”。
正是通过JDBC驱动的转换,才使得使用相同JDBCAPI编写的程序,可以在不同的数据库系统上运行良好。
下面是JDBC编程步骤,以MySQL为例:
查询操作:
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//使用driverManager获取数据库链接
//获取connection代表了java程序和数据库的链接
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/lcma", "root", "iflytek");
//使用conncetion创建一个statement对象
stat = conn.createStatement();
//执行sql语句
rs = stat.executeQuery("select * from student");
//不断使用next()将指针下移一行
while(rs.next()){
System.out.println(rs.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(rs != null){try{rs.close();}catch(SQLException e){e.printStackTrace();}}
if(stat != null){try {stat.close();} catch (SQLException e) {e.printStackTrace();}}
if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}
}
Connection conn = null;
Statement stat = null;
try {
//加载驱动器
Class.forName("com.mysql.jdbc.Driver");
//通过driverManager获取数据库链接
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/lcma", "root", "iflytek");
//使用Connection创建一个Statement
stat = conn.createStatement();
//执行SQL(insert/update/delete)语句,返回数据库影响的行数
int rows = stat.executeUpdate("insert into student (id,name,age,cla_id) values (2,'马小超',22,1)");
if(rows == 1){
System.out.println("插入成功");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(stat != null){try {stat.close();} catch (SQLException e) {e.printStackTrace();}}
if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}
}
通过对前面代码的分析,会发现以下几个问题:
#数据库连接配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/lcma?characterEncoding=utf-8
user=root
password=iflytek
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtil {
private static String url;
private static String user;
private static String password;
static{
//使用properties加载属性文件
Properties prop = new Properties();
try {
InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("com/iflytek/jdbc.properties");
prop.load(is);
//注册驱动(获取属性文件中的数据)
String driverClassName = prop.getProperty("driverClassName");
Class.forName(driverClassName);
//获取属性文件中的url,username,password
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//释放资源
public static void close(Connection conn, Statement stat, ResultSet rs){
if(conn != null){
try {conn.close();} catch (SQLException e) {e.printStackTrace();}
}
if(stat != null){
try {stat.close();} catch (SQLException e) {e.printStackTrace();}
}
if(rs != null){
try {rs.close();} catch (SQLException e) {e.printStackTrace();}
}
}
}
获取数据库连接和释放资源都采用了静态方法,通过类直接调用改方法,实现了公用代码的封装,降低的代码的耦合性。
这时候我们再来看JDBC获取数据库数据代码:
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try{
//通过JdbcUtil获取数据库链接
conn = JdbcUtil.getConnection();
stat = conn.createStatement();
rs = stat.executeQuery("select * from student");
while(rs.next()){
System.out.println(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally {
//通过JdbcUtil关闭资源
JdbcUtil.close(conn, stat, rs);
}
通过现在的代码可以看出,代码简介了很多,没有出现容易出错的配置,获取连接,加载配置文件,关闭资源我们也不需要关心,大大降低了代码的耦合性,提高了代码重用性。
封装过后的代码还是有些问题,就是采用了Statement对数据库操作,如果现在SQL语句需要传入变量,只有采用拼接的方式,这样做有很多缺点,例如拼接容易出错或容易产生SQL注入等。
通过PreparedStatement对数据库操作可以解决Statement带来的缺点,PreparedStatement和Statement区别如下:
Statement的缺点:
升级后的新接口PreparedStatement(推荐):
问号占位符参数:INSERTINTO User(id,name,age,birthday)VALUES(?,?,?,?);
来看一下通过PreparedStatement对数据库操作的代码:
Connection conn = null;
PreparedStatement stat = null;
ResultSet rs = null;
try{
//通过JdbcUtil获取数据库链接
conn = JdbcUtil.getConnection();
stat = conn.prepareStatement("select * from student where name like ? and age = ? ");
stat.setString(1, "%小%");
stat.setInt(2, 22);
rs = stat.executeQuery();
while(rs.next()){
System.out.println(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally {
//通过JdbcUtil关闭资源
JdbcUtil.close(conn, stat, rs);
}
}
1.问号占位符不能加引号。
2.占位符参数设置值从下标从1开始。