Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。我们通常说的JDBC是面向关系型数据库的。
下面是使用JDBC连接MySQL数据库的简单例子:
然后看下jdbc的最重要的几个接口和类
- DriverManager:用于管理一组JDBC驱动程序的基本服务
- DataSource:用于连接到此DataSource对象所表示的物理数据源的工厂。作为DriverManager功能的替代方案,DataSource对象是获取连接的首选方式
- Driver:每个驱动程序类必须实现的接口。DriverManager将尝试加载尽可能多的驱动程序,然后对于任何给定的连接请求,它将依次要求每个驱动程序尝试连接到目标URL
- Connection:与特定数据库的连接(会话)。在连接的上下文中执行SQL语句并返回结果
- Statement:用于执行静态SQL语句并返回其生成的结果的对象
- PreparedStatement:表示预编译SQL语句的对象。SQL语句是预编译的,并存储在PreparedStatement对象中。然后可以使用此对象多次有效地执行此语句
Driver接口的一些驱动程序实现:
看一下现在用的比较多的druid是怎么注册驱动程序的
public class DruidDriver implements Driver, DruidDriverMBean {
private static final DruidDriver instance = new DruidDriver();
// 静态代码块,用于初始化变量
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
registerDriver(instance);
return null;
}
});
}
public static boolean registerDriver(Driver driver) {
try {
// 注意这里,使用jdbc提供的驱动管理器去加载具体的实现
DriverManager.registerDriver(driver);
try {
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName(MBEAN_NAME);
if (!mbeanServer.isRegistered(objectName)) {
mbeanServer.registerMBean(instance, objectName);
}
} catch (Throwable ex) {
if (LOG == null) {
LOG = LogFactory.getLog(DruidDriver.class);
}
LOG.warn("register druid-driver mbean error", ex);
}
return true;
} catch (Exception e) {
if (LOG == null) {
LOG = LogFactory.getLog(DruidDriver.class);
}
LOG.error("registerDriver error", e);
}
return false;
}
// 连接数据库
@Override
public Connection connect(String url, Properties info) throws SQLException {
if (!acceptsURL(url)) {
return null;
}
connectCount.incrementAndGet();
DataSourceProxyImpl dataSource = getDataSource(url, info);
return dataSource.connect(info);
}
private static final ConcurrentMap<String, DataSourceProxyImpl> proxyDataSources = new ConcurrentHashMap<String, DataSourceProxyImpl>(16, 0.75f, 1);
// 这里建立的都是单个连接,不是连接池的实现方式。连接池的实现可以看DruidDataSource
private DataSourceProxyImpl getDataSource(String url, Properties info) throws SQLException {
DataSourceProxyImpl dataSource = proxyDataSources.get(url);
if (dataSource == null) {
DataSourceProxyConfig config = parseConfig(url, info);
Driver rawDriver = createDriver(config.getRawDriverClassName());
DataSourceProxyImpl newDataSource = new DataSourceProxyImpl(rawDriver, config);
{
String property = System.getProperty("druid.filters");
if (property != null && property.length() > 0) {
for (String filterItem : property.split(",")) {
FilterManager.loadFilter(config.getFilters(), filterItem);
}
}
}
{
int dataSourceId = createDataSourceId();
newDataSource.setId(dataSourceId);
for (Filter filter : config.getFilters()) {
filter.init(newDataSource);
}
}
DataSourceProxy oldDataSource = proxyDataSources.putIfAbsent(url, newDataSource);
if (oldDataSource == null) {
if (config.isJmxOption()) {
JMXUtils.register("com.alibaba.druid:type=JdbcStat", JdbcStatManager.getInstance());
}
}
dataSource = proxyDataSources.get(url);
}
return dataSource;
}
}
最后再看下mybatis怎么获取数据库连接的
public interface Transaction {
// 获取数据库连接
Connection getConnection() throws SQLException;
}
/**
* Transaction有三个实现类,分别是SpringManagedTransaction、JdbcTransaction、ManagedTransaction
* ManagedTransaction是一种由容器或框架来管理的事务,而不是 MyBatis 内部来管理
* Transaction 接口的默认实现是 JdbcTransaction
* 现在项目大部分都是使用spring和myBatis框架进行开发
*/
public class SpringManagedTransaction implements Transaction {
@Override
public Connection getConnection() throws SQLException {
if (this.connection == null) {
openConnection();
}
return this.connection;
}
private void openConnection() throws SQLException {
// 通过spring的DataSourceUtils去获取spring dataSource
this.connection = DataSourceUtils.getConnection(this.dataSource);
this.autoCommit = this.connection.getAutoCommit();
this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
LOGGER.debug(() -> "JDBC Connection [" + this.connection + "] will"
+ (this.isConnectionTransactional ? " " : " not ") + "be managed by Spring");
}
}