前言
Java Database Connectivity,Java数据库连接,即Java通过JDBC来操作关系型数据库。(JDBC相当于Java的一个接口,不同关系型数据库通过实例化实现这个接口来具体的实现对数据库的具体CRUD操作)
由于开发中常用JDBC,特此进行简单的代码记录,以便之后直接使用。
常用代码记录
注意导包使用import java.sql.XXX即可(便于适用多种JDBC)DataSource是javax.sql.DataSource包下的
1. JDBC快速入门
首先需要将mysql-connector-java-5.1.48.jar驱动jar包导入项目中,作为项目的依赖jar包(右键add as library),之后加载驱动、创建Conenction、sql、PreparedStatement,执行sql语句并处理结果,最后释放资源。
//1. 加载jdbc驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 创建数据库连接
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&useSSL=false","root","root"); //参数为url,user_name,password
//3. 定义sql
String sql = "select * from table1 where id = ?"; //sql语句中?为占位符,后续记得要setXXX()方法赋值
//4. 创建PreparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5. 给占位符赋值(勿忘)
preparedStatement.setInt(1,1001); //setXXX()方法,第一个参数为列顺序号,第二个参数为列值
//6. 执行sql获得结果
ResultSet resultSet = preparedStatement.executeQuery(); //executeUpdate()方法用来执行写操作(增删改)
//7. 遍历结果输出(处理结果)
if(resultSet.next()){
System.out.println("ID: " + resultSet.getInt(1) // getXXX()参数可为列顺序号(从1开始计数)
+ " name: " + resultSet.getString(2)
+ " sex: " + resultSet.getString("sex")); //etXXX()参数可为列名
}
//8. 释放资源
resultSet.close();
preparedStatement.close();
connection.close();
JDBC操作对象 | 具体含义 | 常用方法 |
---|---|---|
DriverManager | 驱动管理对象 | 1. 注册驱动,对应代码Class.forName("驱动名"); 该方法执行静态代码块,代码块中调用DirverManager的静态方法registerDriver(Driver driver)方法实现注册对应的驱动 2. 获取数据连接 Connection getConnection(url,user,password) |
Connection | 数据库连接对象 | 1. 获取执行sql对象 Statement createStatement(); PreparedStatement preparedStatement(String sql); 2. 管理事务 2.1 开启事务 setAutoCommit(false); 2.2 提交事务 commit(); 2.3 回滚事务 rollback(); |
Statement | 执行sq的l对象 | 执行sql语句: 1.boolean execute(String sql); 执行任意sql 2.boolean executeUpdate(String sql); 执行对数据的增删改操作,执行DDL操作(对数据库CRUD、对数据表CRUD) 3.ResultSet executeQuery(String sql); 执行对数据的查询操作(select语句) |
PreparedStatement | 执行sql的对象 | 执行sql语句: 1. boolean execute(); 2. boolean executeUpdate(); 3. ResultSet executeQuery(); |
ResultSet | 结果集对象(封装查询结果) | 1.next() 游标向下移动一行(起始位从0开始,数据库从1开始)判断下一行是否有数据,有则移动一位并获取这一位的数据 2.getXXX(param) 获取数据,参数为列顺序号/列名 |
注:Statement对象和PreparedStatement对象都是执行sql的对象,区别在于PreparedStatement对象可以防止sql注入,一般开发中也是用的是PreparedStatement。
注:创建Connection对象的url链接中需要加上useUnicode=true&characterEncoding=UTF8,useSSL=false在没有服务器身份验证的情况下不建立SSL连接 参考链接:https://blog.csdn.net/weixin_30609331/article/details/97475853
2. JDBC工具类
由于加载驱动、Connection连接,释放资源这些过程每次对数据库操作都需要执行,如果不抽取出来的话每个方法都得执行一遍太过麻烦代码质量不高,所以一般会单独创建一个JDBCUtils类来建立数据库连接和释放资源,其他类需要的话直接方法调用即可。
public class JDBCUtils {
private static String url;
private static String name;
private static String password;
private static String driver;
static {
Properties properties = new Properties();
try {
properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties")); //加载配置文件(注意配置文件要放在src目录下,与程序的package包同级。否则会报空指针异常)
url = properties.getProperty("url");
name = properties.getProperty("name");
password = properties.getProperty("password");
driver = properties.getProperty("driver");
// Class.forName("com.mysql.jdbc.Driver"); //加载驱动
Class.forName(driver);//将驱动driver同样抽象出来便于改动
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 创建Connection连接
* @return Connection对象
*/
public static Connection getConnection() throws SQLException { //加static关键字修饰方法使得其他方法调用直接使用类名.方法()即可
//抽象出url name password在配置文件中,提高代码复用性
return DriverManager.getConnection(url,name,password);
// return DriverManager.getConnection(
// "jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&useSSL=false",
// "root","root");
}
/**
* 释放资源
* @param resultSet 结果集
* @param preparedStatement 执行SQL的对象
* @param connection 数据库连接对象
*/
public static void close(ResultSet resultSet, PreparedStatement preparedStatement,Connection connection){
if(resultSet!=null){
try {
resultSet.close(); //每一个close都需要独立try-catch,这样可以保证即使一个抛出异常其他的也可正常关闭
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(PreparedStatement preparedStatement,Connection connection){
close(null,preparedStatement,connection);
//鉴于和上面的close方法基本一致,所以直接调用上一个close方法,第一个参数为null(提高代码复用性)
}
}
//调用JBDCUtils工具类举例
//1. 创建connection连接
Connection connection = JDBCUtils.getConnection(); //调用JDBCUtils的静态方法getConnection()创建connection连接对象
//2. 定义sql
String sql = "insert into table1 values(?,?,?)";
//3. 获取PreparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//4. 占位符赋值
preparedStatement.setInt(1,1008);
preparedStatement.setString(2,"liming");
preparedStatement.setString(3,"男");
//5. 执行sql语句
int flag = preparedStatement.executeUpdate(); //返回修改数据库的行数
System.out.println(flag);
//6. 释放资源
JDBCUtils.close(preparedStatement,connection); //调用JDBCUtils工具类的静态方法close释放资源
3. 数据库连接池
在高并发程序中如果每次调用方法创建连接使用结束后释放资源,效率很低。参考线程池搞一个数据库连接池,提前创建好一个固定数据库连接数大小的池子(相当于一个容器),程序调用直接从连接池中拿取连接,用完直接将连接归还即可。
使用连接池可解决节约资源;提高用户高效访问。常见的数据库连接池有c3p0、druid。以druid为例进行代码总结。
# druid.properties文件的配置
url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=root
driver=com.mysql.jdbc.Driver
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大超时时间
maxWait=3000
public class JdbcPool {
private static DataSource dataSource;
private static Connection connection;
static {
Properties properties = new Properties();
try {
properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties); //加载数据库连接池,具体的连接都在配置文件中
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 通过DataSource创建Connection连接
* @return connection对象
*/
public static Connection getConnection(){
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/**
* 释放资源
* @param resultSet 结果集
* @param preparedStatement 执行SQL的对象
* @param connection 数据库连接对象
*/
public static void close(ResultSet resultSet, PreparedStatement preparedStatement,Connection connection){
if(resultSet!=null){
try {
resultSet.close(); //每一个close都需要独立try-catch,这样可以保证即使一个抛出异常其他的也可正常关闭
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(PreparedStatement preparedStatement,Connection connection){
close(null,preparedStatement,connection);
//鉴于和上面的close方法基本一致,所以直接调用上一个close方法,第一个参数为null(提高代码复用性)
}
/**
* 获取连接池
* @return dataSource对象
*/
public static DataSource getDataSource(){
return dataSource;
}
}
4. JDBCTemplate
在Spring开发中提供更简练的JDBC操作接口JDBCTemplate,简化占位符的赋值。
//1. 创建JdbcTemplate对象
JdbcTemplate jdbcTempalte = new JdbcTemplate(JdbcPool.getDataSource());
//2. 定义sql语句
String sql = "delete from table1 where id =?";
//3. 执行sql语句
int count = jdbcTempalte.update(sql,1002);//第二个参数为sql语句占位符赋值
//4. 处理sql执行结果
System.out.println(count);
//JdbcTemplate执行后自动释放资源
//1. 创建JdbcTemplate对象
JdbcTemplate jdbcTempalte = new JdbcTemplate(JdbcPool.getDataSource());
//2. 定义sql语句
String sql = "select * from table1";
//3. 执行sql语句
List<Person> lists = jdbcTempalte.query(sql,new BeanPropertyRowMapper<Person>(Person.class));
//将sql执行结果转换为JavaBean对象(即java实体类对象)
//4. 处理sql执行结果
for(Person person : lists){
System.out.println(person);
}
总结
对于复用性高的常用的知识点、代码及时总结,便于以后复用,提高开发效率。