【0】README
1) 本文部分文字描述转自 core java volume 2 , 测试源代码均为原创, 旨在理解 java数据库编程——元数据(metadata)+web 与企业应用中的连接管理 的基础知识 ;
2)for database connection config, please visit : https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter4/database.properties
【1】元数据(metadata)
1)元数据定义:关于数据库及其表的结构的详细信息; (干货——元数据定义)
2)三类元数据:数据库的元数据, 结果集的元数据, 预备语句参数的元数据; (干货——元数据类型)
3)如果要了解更多信息,从数据库连接中获取一个 DatabaseMetadata对象:
DatabaseMetaData data = conn.getMetadata();
- 3.1)现在就可以获得某些元数据了, 如
ResultSet rs = meta.getTables(null, null, null, new String[]{TABLE”});
将返回一个包含所有数据库表信息的结果集;
4)数据库元数据还有第二个重要应用:
4.1)数据库是非常复杂的, sql 标准为数据库的多样性提供了很大的空间。 DatabaseMatadata 接口中有上百个方法可以用于查询数据库中的相关信息,包括一些奇特的名字进行调用的方法, 如:
meta.supportsCatalogInPrivilegeDefinitions() 和 meta.nullPlusNonNullIsNull();
4.2)DatabaseMetaData 接口用于提供有关数据库的数据, 第二个元数据接口 ResultSetMetaData则用于提供结果集的相关信息。 每当通过查询得到一个结果集时,我们都可以获得该结果集的列数以及每一列的名字, 类型, 和字段宽度。 下面是一个典型循环:
ResultSet mrs = stat.executeQuery(“select * from table”);
ResultSetMetaData meta = mrs.getMetaData();
// index starts from 1 not 0.
for(int i=1; i<=meta.getColumnCount(); i++)
{
String columnName = meta.getColumnLabel(i);
int columnWidth = meta.getColumnDisplaySize(i);
}
5)看个荔枝(查看列名和列宽度)
- 5.1)for souce code, please visit : https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter4/DBMetadataTest.java
- 5.2)key source code at a glance:
public static void main(String[] args)
{
try
{
try(Connection conn = getConnection())
{
String sql = "select * from student";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
ResultSetMetaData metadata = rs.getMetaData();
// index starts from 1 not 0.
for (int i = 1; i <= metadata.getColumnCount(); i++)
{
// 返回该列所建议的名称.
String colName = metadata.getColumnLabel(i);
int colWidth = metadata.getColumnDisplaySize(i);
// 返回给定序列号的列的最大宽度.
System.out.println("colName = " + colName + ", colWidth = " + colWidth);
}
}
}catch(Exception e)
{
e.printStackTrace();
}
- 5.3)relative printing results as follows:
【2】web 与企业应用中的连接管理
1)problem+solution:
- 1.1)problem: 使用 database.properties 文件可以对数据库连接进行简单的设置,但不适用于规模较大的应用, 仅适用于 小型测试程序;
- 1.2)solution: 在 web 或企业中部署JDBC应用时, 数据库连接管理与 java 名字和目录接口(JNDI)是集成在一起的。 遍布企业的数据源的属性可以存储在一个目录中,采用这种方式使得我们可以集中管理用户名, 密码, 数据库名和 JDBC URL;
(干货——引入JNDI==Java Name and Directory Interface,java 名字和目录接口)
Attention)
- A1)我们不再使用 DriverManager, 而是使用 JNDI 访问来定位数据源; (干货——不再使用 DriverManager, 而是使用 JNDI 访问来定位数据)
- A2)数据源就是一个能够提供简单的 JDBC 连接和更多高级服务的接口, 比如执行涉及多个数据库的分布式事务;
- A3) javax.sql 标准扩展包定义了 DataSource 接口;
-
A4)在 java EE 容器中, 甚至不必编程进行 JNDI 查找, 只需在 DataSource 域上使用 Resource 注解, 但加载应用时, 这个数据源引用将被设置;如,
@Resource(name=”jdbc/corejava”)
private DataSource source;- A4.1)当然了, 我们必须配置数据源。如果你编写的数据库程序将在 servlet 容器中运行, 如 tomcat, 或应用服务器中运行, 如GlassFish, 那么必须将 数据库配置信息(包括JNDI名字, JDBC URL, 用户名和密码) 放置在配置文件中, 或在管理员 GUI 中进行设置;
2)problem+solution (干货——这个problem+solution引入了 数据库连接池 的概念 )
-
2.1) problem:涉及建立数据库连接所需的开销问题: 我们的数据库程序给出了两种策略来获取数据库连接: 1,在程序开头建立到数据库的单个连接; 2,在每次需要时都打开一个新连接;
- 2.1.1)但这两种方式都不令人满意: 因为数据库资源是有限的资源, 如果用户要离开应用一段时间, 那么它占用的连接就不应该保持开放状态; 另一方面, 每次查询都获取连接并在随后关闭它的代价也是相当高的;
-
2.2)solution: 建立数据库连接池。
- 2.2.1)这意味着数据库连接在物理上并未被关闭, 而是保留在一个队列中并被反复重用;
3)连接池是一种非常重要的服务:
- 3.1) JDBC规范为实现者提供了用以实现连接池服务的手段;
- 3.2)不过, JDK本身并未实现这项服务,
- 3.3)数据库供应商提供的JDBC驱动程序也没有提供这项服务;
- 3.4)相反, web 容器和应用server 的开发商通常会提供连接池服务的实现; (干货—— web 容器和应用server 的开发商提供连接池服务)
4)连接池的使用对程序员来说是完全透明的:
- 4.1)getConnection方法: 可以通过获取数据源并调用 getConnencion 方法来得到连接池中的连接;
- 4.2)close方法:使用完连接后, 需要调用 close 方法, 该方法并不在物理上关闭连接,而只是告诉连接池已经使用完该连接了。