JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。简言之,JDBC就是Java用于执行SQL语句实现数据库操作的API。
使用JDBC的大体步骤是这样的:
1.注册数据库驱动
通常使用 Class.forName() 的方式进行注册.不同数据库驱动不同,本例采用的是 mysql 驱动.下面介绍了两种数据库对应的驱动样式.
RDBMS | JDBC驱动名称 | URL格式 |
---|---|---|
MySQL | com.mysql.jdbc.Driver | jdbc:mysql://hostName/databaseName |
ORACLE | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@hostName:portNumber:databaseName |
Calss.forName("JDBC驱动名称")
2.获取数据库链接
Connection connection = DriverManager.getConnection();
方法参数可选,不过最终都是调用的此方法
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException{
...
}
3.创建发送sql语句对象
可以根据需求选择创建三种对象: Statement,PreparedStatement,CallableStatement,三者关系为
Statment 接口提供了执行语句和获取结果的基本方法,支持普通的不带参数的sql语句,批量更新、删除等操作。每次使用都需要重新载入sql语句。
PreparedStatement 为 Statment 子接口,添加了 IN 参数的处理方法,支持可变参数sql,采用预编译处理,编译一次,执行多次,较Statment 接口而言,效率大大提高,而且也可以有效的防止sql注入问题。
CallableStatement 为 PreparedStatement 子接口,添加了 OUT , INOUT 参数的处理方法,支持调用存储过程。
4.发送sql语句
发送sql语句方法以及设置动态参数方法很多,建议阅读源码.这里介绍三种发送sql语句方法:
executeQuery() 用于发送查询语句
executeUpdate() 用于发送增添,修改,删除语句
execute() 用于发送所有语句
5.释放资源
接下来进行详细的演示
一、配置文件 jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.20.103:3306/my_test
user=root
password=123456
编写配置文件的目的是数据库有修改时只需修改配置文件,编写的工具类不需要改动.也可以省略此步骤,在工具类内部直接使用数据库的基本配置.
二、JDBC工具类
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* @author YoonaLt
* @date 2019/11/1
* jdbc工具类
*/
public class JdbcUtils {
/**
* 获取数据库链接
*
* @return mysql链接对象
*/
public static Connection getConnection() {
// 获取此类的类加载器
ClassLoader classLoader = JdbcUtils.class.getClassLoader();
// 获取配置文件的输入流
InputStream inputStream = classLoader.getResourceAsStream("jdbc.properties");
// 配置工具
Properties properties = new Properties();
// 加载
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
// 从配置文件读取需要的配置属性
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
// 加载数据库驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取数据库链接
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 释放资源
*
* @param connection 链接对象
* @param statement 发送sql语句对象
* @param resultSet 返回对象集合
*/
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
三、测试
1.建表
public static void createTable() {
// 获取数据库链接
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = null;
String sql = "create table user(id int auto_increment primary key,name varchar(50) comment '姓名'," +
"sex tinyint comment '0男,1女',birthday datetime comment '生日',profession varchar(20) comment '职业')" +
"default charset=utf8;";
try {
// 创建向数据库发送sql语句对象
ps = connection.prepareStatement(sql);
// 发送sql语句
ps.execute();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
JdbcUtils.release(connection, ps, null);
}
}
2.插入数据
public static void insert() {
LocalDateTime localDateTime = LocalDateTime.of(1990, 5, 30, 12, 50, 40);
long l = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
Date dateYoona = new Date(l);
Date dateIU = Date.valueOf("1993-05-16");
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = null;
// 可以直接填写完整的sql语句,也可以使用占位符.
String sql = " insert into user(name,sex,birthday,profession) values ('IU',1,?,'idol'),('Yoona',1,?,'idol')";
try {
ps = connection.prepareStatement(sql);
// 使用占位符时,最好使用占位类型对应的设置方法.也可都使用setObject()方法,第一个参数为占位符位置,从 1 开始,第二个为替换值
ps.setDate(1, dateIU);
ps.setObject(2, dateYoona);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, ps, null);
}
}
3.查询数据
(1)返回的数据确定只有一条
public static void select() {
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = null;
// 查询返回结果集
ResultSet resultSet = null;
String sql = "select * from user where name = ?";
try {
ps = connection.prepareStatement(sql);
ps.setString(1, "Yoona");
resultSet = ps.executeQuery();
if (resultSet.next()) {
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getInt("sex"));
System.out.println(resultSet.getDate("birthday"));
System.out.println(resultSet.getString("profession"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, ps, resultSet);
}
}
(2) 返回的结果可能是多条
public static void selectMany() {
List<Map<String, String>> list = new ArrayList();
Connection connection = JdbcUtils.getConnection();
PreparedStatement cs = null;
ResultSet resultSet = null;
String sql = "select * from user";
try {
cs = connection.prepareStatement(sql);
resultSet = cs.executeQuery();
// 使用while
while (resultSet.next()) {
Map<String, String> m = new HashMap(16);
m.put("name", resultSet.getString("name"));
m.put("profession", resultSet.getString("profession"));
list.add(m);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(connection, cs, resultSet);
}
// 打印验证是否成功取出多条数据
list.forEach(map -> System.out.println(map.get("name") + " 的职业是 " + map.get("profession")));
}
使用 while 循环,将每一个返回集放入准备好的容器中
4.事务
在jdbc中处理事务,是通过使用同一个 Connection 来实现的.
setAutoCommit(boolean autoCommit),设置是否自动提交事务,默认为 true,如果设置为false,则代表开启事务
commit() ,提交事务
rollback(),回滚
public static void commit() {
Connection c = JdbcUtils.getConnection();
PreparedStatement ps = null;
try {
// 开启事务
c.setAutoCommit(false);
// 设置主键冲突,触发事务
String sqlOne = " insert into user(id,name,sex,profession) values (1,'Yoona',1,'idol')";
ps = c.prepareStatement(sqlOne);
ps.executeUpdate();
String sqlTwo = " insert into user(id,name,sex,profession) values (1,'IU',1,'idol')";
ps = c.prepareStatement(sqlTwo);
ps.executeUpdate();
// 提交事务
c.commit();
} catch (SQLException e) {
try {
// 发生异常即回滚
c.rollback();
System.out.println("----------回滚----------");
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
JdbcUtils.release(c, ps, null);
}
}
项目使用的框架对JDBC 已经封装的十分好了,不过适当的了解JDBC的工作步骤还是有助于对框架的理解的.由于本人水平有限,难免出现错误与遗漏,欢迎指正.