JDBC
一:获取数据库连接
1.1 要素一:Driver接口实现类
1.1.1 Driver接口介绍
-
java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
-
在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
- Oracle的驱动:oracle.jdbc.driver.OracleDriver
- mySql的驱动: com.mysql.jdbc.Driver 如果mySql是8.0版,驱动为com.mysql.cj.jdbc.Driver
-
注意将jar包拷贝到Java工程的一个目录中,习惯上新建一个lib文件夹。
1.1.2 加载与注册JDBC驱动
-
加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名
- Class.forName(“com.mysql.jdbc.Driver”);
-
注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序
-
使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动
-
通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。
-
1.2 要素二:URL
-
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
-
JDBC URL的标准由三部分组成,各部分间用冒号分隔。
-
jdbc:子协议:子名称
-
协议:JDBC URL中的协议总是jdbc
-
子协议:子协议用于标识一个数据库驱动程序
-
子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名
-
MySQL的连接URL编写方式:
- jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
- jdbc:mysql://localhost:3306/yang
- jdbc:mysql://localhost:3306/yang?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
- 如果是mySql8.0及以上要加时区jdbc:mysql://localhost:3306/rentcar?&useSSL=false&serverTimezone=UTC
-
1.3 要素三:用户名和密码
- user,password可以用“属性名=属性值”方式告诉数据库
- 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
1.4 数据库连接方式举例
1.4.1 连接方式一
@Test
public void connection1() {
try {
//1.实例化Driver
String className = "com.mysql.jdbc.Driver";
Class clazz = Class.forName(className);
Driver driver = (Driver) clazz.newInstance();
//2.提供url,指明具体操作的数据
String url = "jdbc:mysql://localhost:3306/yang";
//3.提供Properties的对象,指明用户名和密码
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
//4.调用driver的connect(),获取连接
Connection conn = driver.connect(url, info);
System.out.println(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
这里使用反射实例化Driver,不在代码中体现第三方数据库的API。体现了面向接口编程思想。
1.4.2 连接方式二
@Test
public void connection2() {
try {
//1.数据库连接的4个基本要素:
String url = "jdbc:mysql://localhost:3306/yang";
String user = "root";
String password = "abc123";
String driverName = "com.mysql.jdbc.Driver";
//2.实例化Driver
Class clazz = Class.forName(driverName);
Driver driver = (Driver) clazz.newInstance();
//3.注册驱动
DriverManager.registerDriver(driver);
//4.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
使用DriverManager实现数据库的连接。
前面两种方法直接将URL和密码放在代码中,实际开发中不这样使用,而是放在配置文件中
1.4.3 连接方式三
@Test
public void connection3() throws Exception {
//1.加载配置文件
InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
//2.读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//3.加载驱动
Class.forName(driverClass);
//4.获取连接
Connection conn = DriverManager.getConnection(url,user,password);
System.out.println(conn);
}
其中,配置文件声明在工程的src目录下:【jdbc.properties】
user=root
password=abc123
url=jdbc:mysql://localhost:3306/yang
driverClass=com.mysql.jdbc.Driver
二:DAO及相关实现类
- DAO:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete),而不包含任何业务相关的信息。有时也称作:BaseDAO
- 作用:为了实现功能的模块化,更有利于代码的维护和升级。
【BaseDAO.java】
package baseDAO;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @author programpig
* @create
*/
public abstract class BaseDAO {
private QueryRunner runner = new QueryRunner();
public int carUpdate(Connection connection,String sql,Object ... obj) throws SQLException {
int count = runner.update(connection, sql,obj);
return count;
}
public <T> T getInstance(Connection connection,String sql,Class<T> cls,Object ... obj) throws SQLException {
BeanHandler<T> beanHandler = new BeanHandler<>(cls);
T query = runner.query(connection, sql, beanHandler, obj);
return query;
}
public <T> List<T> getList(Connection connection,String sql,Class<T> cls,Object ... obj) throws SQLException {
BeanListHandler<T> beanHandler = new BeanListHandler<>(cls);
List<T> list = runner.query(connection, sql, beanHandler, obj);
return list;
}
public <T> T getValue(Connection connection,String sql,Object ... obj) throws SQLException {
ScalarHandler handler = new ScalarHandler();
Object value = runner.query(connection, sql, handler, obj);
return (T)value;
}
}
【CarDAO.java】
public interface CarDAO {
void addCar(Connection connection,Car car) throws SQLException;
void deleteById(Connection connection,int id) throws SQLException;
void updateCar(Connection connection,Car car) throws SQLException;
Car getCar(Connection connection,int id) throws SQLException;
List<Car> getAll(Connection connection) throws SQLException;
long getCount(Connection connection) throws SQLException;
}
【CarDaoImpl.java】
package car;
import baseDAO.BaseDAO;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @author programpig
* @create
*/
public class CarDAOImpl extends BaseDAO implements CarDAO{
@Override
public void addCar(Connection connection, Car car) throws SQLException {
String sql = "insert into cars(type,num,money,status)values(?,?,?,?)";
int count = carUpdate(connection, sql, car.getType(), car.getNum(), car.getMoney(), car.getStatus());
System.out.println("添加了"+ count +"辆车");
}
@Override
public void deleteById(Connection connection, int id) throws SQLException {
String sql = "delete from cars where id = ?";
carUpdate(connection,sql,id);
System.out.println("删除成功");
}
@Override
public void updateCar(Connection connection, Car car) throws SQLException {
String sql = "update cars set type = ?,num = ?,money = ? where id = ?";
carUpdate(connection,sql,car.getType(),car.getNum(),car.getMoney(),car.getId());
System.out.println("修改成功");
}
@Override
public Car getCar(Connection connection, int id) throws SQLException {
String sql = "select type,num,money,status from cars where id = ?";
Car car = getInstance(connection, sql, Car.class, id);
return car;
}
@Override
public List<Car> getAll(Connection connection) throws SQLException {
String sql = "select id,type,num,money,status from cars";
List<Car> carList = getList(connection, sql, Car.class);
return carList;
}
@Override
public long getCount(Connection connection) throws SQLException {
String sql = "select count(*) from cars";
Object value = getValue(connection, sql);
return (long)value;
}
}
三:数据库连接池
Druid数据库连接池
Druid是阿里巴巴开源平台上一个数据库连接池实现
将连接数据库的操作封装到一个工具包内,使用加载配置文件的方法
package druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author programpig
* @create
*/
public class JDBCUtils {
public static Connection getConnection() throws Exception {
//通过数据源获取连接
Connection connection = dataSource.getConnection();
return connection;
}
private static DataSource dataSource ;
static{
//提供Properties,并加载指定配置文件的流
try {
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
dataSource = DruidDataSourceFactory.createDataSource(pros); //由于静态代码块只执行一次,所以我们自始至终就创建过一个DataSource
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 关闭连接
* */
public static void close(Connection connection){
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
其中,src下的配置文件为:【druid.properties】
driverClassName=com.mysql.cj.jdbc.Driver
username=root
url=jdbc:mysql://localhost:3306/yang?&useSSL=false&serverTimezone=UTC
password=123abc
导入的jar包
四:Apache-DBUtils实现CRUD操作
上述DAO设计采取的此种操作实现CRUD
4.1 Apache-DBUtils简介
-
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
-
API介绍:
- org.apache.commons.dbutils.QueryRunner
- org.apache.commons.dbutils.ResultSetHandler
- 工具类:org.apache.commons.dbutils.DbUtils
4.2 主要API的使用
4.2.1 DbUtils
- DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
- public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
- public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。
- public static void commitAndClose(Connection conn)throws SQLException: 用来提交连接的事务,然后关闭连接
- public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
- public static void rollback(Connection conn)throws SQLException:允许conn为null,因为方法内部做了判断
4.2.2 QueryRunner类
-
该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
-
QueryRunner类提供了两个构造器:
- 默认的构造器
- 需要一个 javax.sql.DataSource 来作参数的构造器
-
QueryRunner类的主要方法:
-
更新
- public int update(Connection conn, String sql, Object… params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
-
插入
- public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
-
批处理
- public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
- public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句
-
查询
- public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
-
jar包:链接:
https://pan.baidu.com/s/1ogTCnovsM4vY4wlR0sTVFw
提取码:abc1
链接:https://pan.baidu.com/s/1_iSlcbTIhKZ3zvp3xbg_Kw
提取码:abc2
链接:https://pan.baidu.com/s/10V1JeyP8a_057p9nFatApQ
提取码:abc3