1、 JDBC
1.1 概念
JDBC:Java DataBase Connectivity
Java数据库连接,Java语言操作数据库
JDBC本质:其实是官方(SUN公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
1.2 快速入门
步骤:
- 导入驱动jar包(官方下载地址:https://dev.mysql.com/downloads/)
1. 复制mysql-connector-java-8.0.26.jar包到项目的libs(没有的话新建即可)目录下
2. 右键–>Add AS Library - 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 获取执行sql语句的对象 Startement
- 执行sql,接收返回结果
- 处理结果
- 释放资源
public static void main(String[] args){
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://db.mysqltest.mijiaoyu.cn:3306/edu_teachingplan4", "root", "Dxmmysql20A20!@#");
// sql语句
String sql = "select * from tp_interveneobject limit 10";
// 获取执行sql对象Statement
statement = conn.createStatement();
// 执行sql
resultSet = statement.executeQuery(sql);
// 处理sql
while (resultSet.next()) {
System.out.println(resultSet.getInt("code"));
System.out.println(resultSet.getString("name"));
};
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.3 详解各个对象
- DriverManager:驱动管理对象
功能:
1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager
写代码时使用:Class.forName(“com.mysql.cj.jdbc.Driver”);
通过查看源码发现:在com.mysql.cj.jdbc.Driver类中存在静态代码块,加载Driver类进内存后则会自动执行
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
2. 获取数据库连接
方法:static Connection getConnection(String url, String user, String password)
参数:
1. url:语法:jdbc:mysql:// ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db3
细节:如果链接的是本机的mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql///数据库名称
2. user:用户名
3. password:密码
-
Connection:数据库连接对象
功能:1. 获取执行sql的对象 Statement createStatement(); PreparedStatement prepareStatement(String sql); 2. 管理事务 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务 提交事务:conmmit(); 回滚事务:rollback();
-
Statement:执行sql的对象
功能:1. 执行sql 1. boolean execute(String sql):可以执行任意的sql 2. int executeUpdate(String sql):执行的是DML(增删改)语句、DDL(create/alter/drop)语句 返回值: 影响的行数,可以通过影响的行数判断DML语句是否执行成功 3. ResultSet executeQuery(String sql):执行DQL(select)语句
-
ResultSet:结果集对象,封装查询结果
1. boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是返回false,如果不是则返回true(true有数据,false没有数据) 2. getXxx(参数):获取数据 Xxx:代表数据类型 如:getInt()、getString() 参数: 1. int:代表列的编号,从1开始。 如:getString(1) 2. String:代表列名称。如:getDouble("balance") 注意: 使用步骤: 1. 游标向下移动一行 2. 判断是否有数据 3. 获取数据
-
PreparedStatement:执行sql的对象
1. sql注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全问题 1. 输入用户名,输入密码:a' or 'a' = 'a 2. sql:select * from user where username = 'zhangsan' and password = 'a' or 'a' = 'a'; 2. 解决sql注入问题:使用PreparedStatement对象来解决 3. 预编译的sql:参数使用?作为占位符 4. 步骤: 1. 导入驱动jar包 2. 注册驱动 3. 获取数据库连接对象 Connection 4. 定义sql 注意:sql的参数使用?作为占位符。如:select * from user where username = ? and password = ?; 5. 获取执行sql语句的对象PreparedStatement Connection.preparedStatement(String sql) 6. 给参数?赋值 方法:setXxx(参数1, 参数2) 参数1:?的位置编号 从1开始 参数2:?的值 7. 执行sql,接收返回结果,不需要传递sql语句 8. 处理结果 9. 释放资源 5. 注意:后期都会使用 PreparedStatement来完成增删改查的所有操作 1. 可以防止sql注入 2. 效率更高
// JDBC工具类
public class JdbcUtil {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
try {
// 创建Properties集合类对象
Properties pro = new Properties();
// 获取src路径下文件的方式-->ClassLoader类加载器
ClassLoader classLoader = JdbcUtil.class.getClassLoader();
// 获取URL资源定位符对象
URL resource = classLoader.getResource("jdbc.properties");
if (resource != null) {
// 获取文件绝对路径
String path = resource.getPath();
// 加载文件
pro.load(new FileReader(path));
}
// 获取数据并赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取Connection对象
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
// 释放资源
public static void close(PreparedStatement ps, Connection conn) {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs, PreparedStatement ps, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 登录案例
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String user = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
boolean flag = login(user, password);
if (flag) {
System.out.println("登录成功!");
} else {
System.out.println("用户名或密码错误!");
}
}
public static boolean login(String user, String password) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
if (user == null || password == null) {
return false;
}
try {
conn = JdbcUtil.getConnection();
String sql = "select * from user where username = ? and password = ?";
ps = conn.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, password);
resultSet = ps.executeQuery();
return resultSet.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(resultSet, ps, conn);
}
return false;
}
1.4 JDBC管理事务
如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
-
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务(执行sql前开启事务)
-
提交事务:conmmit();(执行完所有sql提交事务)
-
回滚事务:rollback();(在catch中回滚事务)
2、数据库连接池
2.1 概念
其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器
2.2 好处
- 节约资源
- 用户访问高校
2.3 实现
- 标准接口:DataSource java.sql包下
方法:
- 获取连接:getConnection()
- 归还连接:Connection.close() 如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接,而是归还连接 - 一般不用去实现它,有数据库厂商来实现
-
C3P0:数据库连接池技术
步骤: 1. 导入jar包(两个)c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,不要忘记导入数据库驱动jar包 2. 定义配置文件 1. 名称:c3p0.properties或者c3p0-config.xml 2. 路径:直接将文件放在src目录下即可 3. 创建核心对象,数据库连接池对象 ComboPooledDataSource 4. 获取连接:getConnection
-
Druid:数据库连接池实现技术,由阿里巴巴提供
// druid.properties driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/python username=root password=xxxxx filters=stat initialSize=2 maxActive=300 maxWait=60000 timeBetweenEvictionRunsMillis=60000 minEvictableIdleTimeMillis=300000 validationQuery=SELECT 1 testWhileIdle=true testOnBorrow=false testOnReturn=false poolPreparedStatements=false maxPoolPreparedStatementPerConnectionSize=200
1. 步骤: a. 导入jar包 druid-1.0.9.jar b. 定义配置文件 1. 是properties形式的 2. 可以叫任意名称,可以放在任意目录下 c. 获取数据库连接池对象:通过工厂类来获取:DruidDataSourceFactory d. 获取连接:getConnection 2. 定义工具类 a. 定义一个类 JDBCUtils b. 提供静态代码块加载配置文件,初始化连接池对象 c. 提供方法 1. 获取连接方法:通过数据库连接池获取连接 2. 释放资源 3. 获取连接池的方法
-
// Druid工具类
public class JDBCUtils {
// 定义成员变量DataSource
private static DataSource ds;
static {
try {
// 加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
// 获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
// 释放资源
public static void close(ResultSet rs, PreparedStatement ps, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 获取连接池方法
public static DataSource getDataSource() {
return ds;
}
}