JDBC(Java DataBase Connectivity,Java 数据库连接)
????????JDBC(Java DataBase Connectivity,Java 数据库连接):sun公司为了简化和统一Java连接数据库,定义的一套规范(类,接口)。
JDBC,是用于Java编程语言和数据库之间的数据库无关连接的标准Java API。
JDBC和MySQL驱动的关系:接口(JDBC)与实现(MySQL驱动jar包)的关系
JDBC API详解
1 | DriverManager:驱动管理器(注册驱动) | Driver :此接口处理与数据库服务器的通信 | 2 | Connection:代表连接对象(获得连接) | 事务操作: 1.void setAutoCommit(boolean autoCommit) false--手动开启事务(start transaction) 2.void commit();提交事务(commit) 3.void rollback();回滚事务(rollback) | 3 | Statement:执行sql语句对象 | 1.执行查询 Result executeQuery(String sql) 返回结果集 2.执行增删改 int excuteUpdate(String sql) 返回受影响的行数 | 4 | ResultSet:结果集 | 在使用Statement 对象执行SQL查询后,这些对象保存从数据库检索的数据。 它作为一个迭代器并可移动ResultSet 对象查询的数据。 | 5 | PreparedStatement接口:继承Statement接口 | 在执行sql语句之前,将sql语句进行提前编译。使用PreparedStatement对象解决登录案例中的sql注入漏洞问题 ,更加安全性 |
import com.mysql.jdbc.Driver;
import java.sql.*;
//0.拷贝mysql的驱动包到模块下,并添加依赖(add as library)
//1.注册驱动
//2.获得连接
//3.创建执行sql语句对象
//4.执行sql语句,得到结果
//5.释放资源
public class Test {
public static void main(String[] args) throws SQLException {
//1.注册驱动
DriverManager.registerDriver(new Driver());
//2.获得连接
String url = "jdbc:mysql://localhost:3306/mysql_person";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
//3.创建执行sql语句对象
Statement statement = connection.createStatement();
//4.执行sql语句,得到结果
String sql = "select * from user";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("username"));
System.out.println(resultSet.getObject("password"));
System.out.println(resultSet.getObject("nickname"));
}
//5.释放资源
resultSet.close();
statement.close();
connection.close();
}
}
JDBCUtils工具类的抽取
db.properties配置文件:
????????driverClass=com.mysql.jdbc.Driver ????????url=jdbc:mysql://localhost:3306/mysql_person ????????username=root ????????password=root
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String driverClass;
private static String url;
private static String username;
private static String password;
static {
try {
// 创建Properties对象
Properties pro = new Properties();
// 加载配置文件
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
pro.load(is);
// 取数据
driverClass = pro.getProperty("driverClass");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
// 注册驱动
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获得连接
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
// 获得连接
Connection connection = DriverManager.getConnection(url, username, password);
// 返回连接
return connection;
}
/**
* 释放资源
* @param resultSet
* @param statement
* @param connection
*/
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
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();
}
}
}
}
为什么要使用连接池
????????Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了(close)。每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化。
程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中。每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中。
连接池原理
-
程序一开始就创建一定数量的连接,放在一个容器(集合)中,这个容器称为连接池。 -
使用的时候直接从连接池中取一个已经创建好的连接对象, 使用完成之后 归还到池子 -
如果池子里面的连接使用完了, 还有程序需要使用连接, 先等待一段时间(eg: 3s), 如果在这段时间之内有连接归还, 就拿去使用; 如果还没有连接归还, 新创建一个, 但是新创建的这一个不会归还了(销毁) -
集合选择LinkedList
-
增删比较快 -
LinkedList里面的removeFirst()和addLast()方法和连接池的原理吻合
1.C3P0连接池
db.properties配置文件:
????????driverClass=com.mysql.jdbc.Driver ????????url=jdbc:mysql://localhost:3306/mysql_person ????????username=root ????????password=root
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3P0Utils {
//- 在工具类中,创建一个唯一连接池对象(private static final)
private static final ComboPooledDataSource DATA_SOURCE = new ComboPooledDataSource();
//- 在工具类中,定义一个公共的静态方法用来获取连接池对象
/**
* 获得连接池
* @return
*/
public static DataSource getDataSource(){
return DATA_SOURCE;
}
//- 在工具类中,定义一个公共的静态方法用来获取连接对象
/**
* 获得连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DATA_SOURCE.getConnection();
}
//- 在工具类中,定义一个公共的静态方法用来释放资源
/**
* 释放资源
* @param resultSet
* @param statement
* @param connection
*/
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
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();
}
}
}
}
2.druid连接池
druid.properties配置文件: ????????# 数据库连接参数 ????????driverClassName=com.mysql.jdbc.Driver ????????url=jdbc:mysql://localhost:3306/mysql_person ????????username=root ????????password=root ????????# 连接池的参数 ????????initialSize=10 ????????maxActive=20 ????????maxWait=2000
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtils {
//- 在工具类中,定义一个连接池类型的成员变量
private static DataSource dataSource;
//- 在工具类的静态代码块中,加载配置文件,创建连接池对象,并赋值给连接池类型的成员变量
static {
try {
//- 创建Properties对象,加载配置文件
Properties pro = new Properties();
InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//- 创建DRUID的连接池对象,传入Properties对象
dataSource = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
//- 在工具类中,提供一个公共的静态方法用来获取连接池对象
public static DataSource getDataSource(){
return dataSource;
}
//- 在工具类中,提供一个公共的静态方法用来获取连接对象
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//- 在工具类中,提供一个公共的静态方法用来释放资源
/**
* 释放资源
* @param resultSet
* @param statement
* @param connection
*/
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
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();
}
}
}
}
3.DbUtils工具类
????????DbUtils,是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
能够使用DBUtils完成CRUD:
????????创建QueryRunner对象:public QueryRunner(DataSource datasource); ????????增删改: int update(String sql,Object... args); ????????查询: 返回值 query(String sql,ResultSetHandler<T> rsh,Object... args) ResultSetHandler接口的实现类: ? ? ? ? BeanHandler:适合查询结果是一条记录的,会把这条记录的数据封装到一个javaBean对象中 ? ? ? ? BeanListHandler:适合查询结果是多条记录的,会把每条记录的数据封装到一个javaBean对象中,然后把这些javaBean对象添加到List集合中 ? ? ? ? ColumnListHandler:适合查询结果是单列多行的,会把该列的所有数据存储到List集合中 ? ? ? ? ScalarHandler:适合查询结果是单个值的,会把这个值封装成一个对象
ResultSetHandler接口的实现类:
//需求:使用DBUtils完成增删改
//1.创建QueryRunner对象,传入连接池对象
//2.调用update方法,传入sql语句,以及sql语句需要的参数值
public class Demo {
// 1.创建QueryRunner对象,传入连接池对象
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
@Test
public void insert() throws SQLException {
// 2.调用update方法,传入sql语句,以及sql语句需要的参数值
int rows = qr.update("insert into user values(null,?,?,?)", "along", "123456", "张三");
System.out.println("受影响的行数:"+rows);
}
@Test
public void update() throws SQLException {
// 2.调用update方法,传入sql语句,以及sql语句需要的参数值
int rows = qr.update("update user set username = ? where id = ?", "al",10);
System.out.println("受影响的行数:"+rows);
}
@Test
public void delete() throws SQLException {
// 2.调用update方法,传入sql语句,以及sql语句需要的参数值
int rows = qr.update("delete from user where id = ?", 10);
System.out.println("受影响的行数:"+rows);
}
}
MyBatis连接池
Mybatis自带连接池,Mybatis的DataSource数据源(连接池)分为三类:
-
POOLED 【默认】使用连接池的数据源。 -
UNPOOLED 不使用连接池的数据源。 -
JNDI 使用 JNDI 实现的数据源,不一样的服务器获得的DataSource是不一样的. 注意: 只有是web项目或者Maven的war工程, 才能使用。我们用的是tomcat, 用的连接池是dbcp。
MyBatis 在初始化时,解析核心配置文件,根据<dataSource>的 type 属性来创建相应类型的的数据源DataSource,即:
-
type=”POOLED”: MyBatis 会创建 PooledDataSource 实例, 使用连接池 ? -
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例, 没有使用的,只有一个连接对象的 ? -
type=”JNDI”: MyBatis 会从 JNDI 服务上(tomcat ... jboss...)查找 DataSource 实例,然后返回使用。只有在web项目里面才有的,用的是服务器里面的。 默认会使用tomcat里面的dbcp
-
一般我们不会直接使用MyBatis默认的连接池,因为它的效率并不高,当我们学习了Spring或者实际开发中一般都会使用第三方的连接池【druid hikariCP】
//需求:使用MyBatis查询所有的用户, 封装到List集合(MyBatis入门步骤)
//创建数据库,创建Maven工程【Javase】,添加MyBatis依赖
//创建Javabean(User.java)
//创建dao接口(UserDao.java)
//创建dao接口映射文件 (UserDao.xml)
//创建MyBatis核心配置文件(mybatis-config.xml)
//执行测试
@Test
public void method01() throws IOException {
//1.需要得到MyBatis核心配置文件的文件流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.加载MyBatis核心配置文件 获得SqlSessionFactory对象
//使用了建造者模式 和 工厂模式 得到SqlSessionFactory 相当于连接池对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.获取SqlSession对象 相当于Connection对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取dao接口的代理对象 使用了代理模式
UserDao userDao = sqlSession.getMapper(UserDao.class);
//5.调用方法操作
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println("user = " + user);
}
//6.关闭对象
sqlSession.close();
is.close();
}
SqlSessionFactoryUtils工具类
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SqlSessionFactoryUtils {
private static SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
private static SqlSessionFactory sqlSessionFactory;
//1.2步定义在静态代码块里面(配置文件不需要读取一次, 全局只需要一个SqlSessionFactory)
static {
//1.读取SqlMapConfig.xml
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.根据SqlMapConfig.xml创建SqlSessionFactory(相当于连接池)
sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获得SqlSession
* @return
* @throws IOException
*/
public static SqlSession openSqlSession() throws IOException {
//3.打开SqlSession(相当于Connection)
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
/**
* 提交释放资源
* @param sqlSession
*/
public static void commitAndClose(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.commit();
sqlSession.close();
}
}
/**
* 回滚释放资源
* @param sqlSession
*/
public static void rollbackAndClose(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.rollback();
sqlSession.close();
}
}
}
|