`
yeshaoting
  • 浏览: 684410 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[反射机制]建立数据库连接

    博客分类:
  • J2SE
 
阅读更多

 

 

11. 利用反射机制建立数据库连接

解析数据库数据源配置文件(.xml),利用反射机制将配置文件中设置的数据源参数设置到 Class 类实例中,然后将该 Class 类实例强制转换成对应的数据源类。

 

1. 自定义数据源配置文件data-source-config.xml

简单提出一些约束条件。这些约束在解析该数据源配置文件时用到。

<?xml version="1.0" encoding="UTF-8"?>

 

<!-- quote from struts-config.xml -->

<!--

   

    数据源配置文件几点约束:

    1. <data-sources>节点下定义了一套数据源<data-source>[JDBC 2.0 Standard Extension]

    2. 节点拼写大小写敏感,目前有且只有三级节点

    3. 只允许有一个根节点<data-sources>

    4. 出现多个 id <data-source>节点,以第一个为准

   

    数据源查找方式:

    1. <data-source>节点数 < 1, 即节点数为0

       未设置数据源,报错

   

    2. 默认数据源方式

       <data-source>节点未设置 id 属性值或 id 属性值为null<data-source>

      

    3. 指定数据源方式

       匹配<data-source>节点 id 属性值

             

 -->

<data-sources>

    <data-source type="org.apache.commons.dbcp.BasicDataSource">

       <set-property property="driverClassName" value="com.mysql.jdbc.Driver" />

       <set-property property="url" value="jdbc:mysql://localhost:3306/mydb" />

       <set-property property="username" value="root" />

       <set-property property="password" value="root" />

       <set-property property="maxActive" value="30" />

       <set-property property="maxIdle" value="10" />

       <set-property property="maxWait" value="1000" />

    </data-source>

</data-sources>

 

 

2. 解析配置文件

利用 XML 解析工具包解析配置文件。本文采用 jdom 来解析配置文件。

全局变量:

/**

 * Copyright (c) 2011 Trusted Software and Mobile Computing(TSMC)

 * All right reserved.

 *

 * Created on Aug 19, 2011 6:37:38 PM

 * http://jarg.iteye.com/

 * Author: Jarg Yee <yeshaoting@gmail.com>

     */ 

 

 

    /** 配置文件路径 */

    private static final String CONFIG = "data-source-config.xml";

   

    /** 默认配置数据源 id 属性值 */

    private static final String DEFAULT_ID = "null";

   

    /** 配置文件节点属性名 */

    private static final String ATT_TYPE = "type";

    private static final String ATT_ID = "id";

    private static final String ATT_PROPERTY = "property";

    private static final String ATT_VALUE = "value";

    private static final String ATT_REF = "ref";

   

    /** 配置文件节点名 */

    private static final String NODE_DATA_SOURCES = "data-sources";

    private static final String NODE_DATA_SOURCE = "data-source";

    private static final String NODE_SET_PROPERTY = "set-property";

   

    /** 反射机制获取方法名前缀 */

    private static final String PREFIX_SET = "set";

    private static final String PREFIX_GET = "get";

   

    /** 二种基本类型 */

    private static final String TYPE_INT = "int";

    private static final String TYPE_LONG = "long";

   

 

2.1 初始化配置文件

加载自定路径的配置文件,该路径是相对于类加载目录的路径。

Eclipse C/S项目中相对于classpathbin目录,Eclipse B/S项目中相对于classpathWebRoot/classes目录。

关键代码: 

    /**

     * 初始化配置

     * */

    private void initConfig(String config)

    {

       InputStream in = this.getClass().getClassLoader().getResourceAsStream(config);

       SAXBuilder builder = new SAXBuilder();

      

      

       try

       {

           Document doc = builder.build(in);

           root = doc.getRootElement();

       }

       catch (Exception e)

       {

           System.out.println("配置文件" + config + "丢失");

           e.printStackTrace();

       }

    }

   

 

2.2 选择数据源节点

循环获取数据源节点<data-source>属性 id 值与传入的数据源节点 id 值匹配,获取对应的数据源节点。

关键代码:

    /**

     * 需要加上 "" ,否则无法与null匹配成功

     * 不知道什么原因

     * */ 

    for(int i=0; i<dataSources.size(); i++)

    {

       Element element = dataSources.get(i);

       if(id.equals("" + element.getAttributeValue(ATT_ID)))

       {

           dataSourceElement = element;

       }

    }

   

 

2.3 创建、设置、获取数据源实例

[创建数据源实例] 先获取数据源type属性值(声明数据源类完全限定名称),通过这个完全限定名称字符串创建 Class 类实例。

 

[设置数据源实例] 再获取当前数据源节点<datab-source>下所有属性设置节点<set-property>

然后获取每个属性设置节点<set-property>namevalue属性值,根据name值获取字段类型。

不同类型值转换过程通过getMatchValue()方法来实现,其用途是:

a. 利用反射机制获取对应的setter方法的方法getMethod(),需要setter方法参数类型

b. value属性值读出来的是String类型(可以看作是Object类型),需要转换成setter方法对应的类型值。

例如:org.apache.commons.dbcp.BasicDataSource.BasicDataSource setMinIdle()方法:

    public synchronized void setMinIdle(int minIdle)

 

[获取数据源实例] 最后,通过invoke()方法完成setter方法调用,将属性设置节点<set-property>属性值通过相应的setter方法设置到 Class 类实例相应的属性中。将 Class 类实例强制转换成 DataSource(所有数据源类的父类),返回。

 

关键代码:

    /**

     * 设置数据源数据

     * @param dataSourceElement Element - 选择的数据源节点

     * @throws Exception

     * */

    private DataSource newInstance(Element dataSourceElement) throws Exception

    {

       String type = dataSourceElement.getAttributeValue(ATT_TYPE);

       if(type == null)

       {

           throw new Exception("未定义数据源类型");

       }

 

       Class<?> clazz = Class.forName(type);

       Object obj = clazz.newInstance();

      

       List<Element> properties = dataSourceElement.getChildren(NODE_SET_PROPERTY);

      

       for(int i=0; i<properties.size(); i++)

       {

           Element property = properties.get(i);

           String name = property.getAttributeValue(ATT_PROPERTY);

           if(name == null)

           {

              throw new Exception("未定义属性名");

           }

          

           String value = property.getAttributeValue(ATT_VALUE);

           if(value == null)

           {

              throw new Exception("未定义属性值");

           }

          

           /** 为了获取参数类型 */

           Field field = clazz.getDeclaredField(name);

           Class<?> fieldType = field.getType();

          

           String methodName = getMethodName(PREFIX_SET, name);

           Method method = clazz.getMethod(methodName, fieldType);

           method.invoke(obj, getMatchValue(fieldType, value));

          

       }

       return (DataSource)obj;

    }

   

    /**

     * 获取与字段类型相匹配的值

     * */

    private Object getMatchValue(Class<?> fieldType, String value)

    {

      

       /**

        * 目前只有二类基本类型转换

        * */

       if(fieldType.getName().equals(TYPE_INT))

       {

           return Integer.parseInt(value);

       }

       else if(fieldType.getName().equals(TYPE_LONG))

       {

           return Long.parseLong(value);

       }

       else

           return value;

    }

   

 

2.4 建立数据库连接

通过上一步返回的数据源javax.sql.DataSource(这是一个接口)实例调用getConnection()方法建立数据库连接。

 

关键代码:

   

    /**

     * 获取指定数据源的数据库

     * @throws Exception

     * */

    protected static Connection getConnection(DataSourceConfig dataSourceConfig, String id)

           throws Exception

    {

       return dataSourceConfig.getDataSource(id).getConnection();

    }

   

 

2.5 提供获取数据库连接用户接口

封装具体的数据库内部实现,将相关方法权限设置为 protected

利用getConnection(String id)获取指定数据源的数据库连接。

 

关键代码:

 

    /**

     * 获取指定数据源的数据库连接

     * 不支持自定义用户名,密码方式

     * @param id String

     * */

    public Connection getConnection(String id)

    {

       Connection conn = null;

       try

       {

           conn = DataSourceConfig.getConnection(dataSourceConfig, id);

       }

       catch (Exception e)

       {

           e.printStackTrace();

       }

       return conn;

    }

   

 

  • ex2.rar (1011.9 KB)
  • 下载次数: 4
0
4
分享到:
评论

相关推荐

    通过类反射机制实现底层数据库连接

    在Hibernate中,类反射机制扮演着关键角色,尤其是在初始化SessionFactory和建立数据库连接的过程中。 首先,让我们了解反射的基本使用。在Java中,`Class`类代表了运行时的类信息,我们可以使用`Class.forName()`...

    JAVA反射机制和JDBC和各种数据库的连接

    2. 建立连接:通过`DriverManager.getConnection()`方法建立数据库连接,通常需要提供URL、用户名和密码。 3. 创建Statement:`Connection`对象的`createStatement()`方法创建`Statement`对象,用于执行SQL语句。 ...

    反射连接数据库

    在“反射连接数据库”的场景中,我们利用反射机制动态地创建对象并调用其方法,以实现与MySQL数据库的交互,从而避免硬编码SQL语句,提高代码的灵活性和可维护性。 首先,我们需要理解Java JDBC(Java Database ...

    java 解析xml类映射数据库 数据库操作 反射机制 源码

    2. 数据库连接:使用JDBC建立数据库连接,获取Connection对象。 3. 数据库操作:创建Statement或PreparedStatement对象,执行SQL,处理ResultSet。 4. 反射应用:根据XML映射信息,使用反射动态地实例化对象,设置...

    POI +反射导出数据库到excel

    通过JDBC,我们可以建立数据库连接,执行SQL语句,然后将结果集转换为Java对象,以便于填充到Excel表格中。 **文件列表解析**: 1. **poi-ooxml-schemas-3.9-20121203.jar**:包含OOXML(Office Open XML)的模式...

    JDBC(连接池)连接三种数据库

    在实现上,我们可以使用反射机制动态地加载不同的数据库驱动,以支持Oracle、MySQL和SQL Server。反射是Java语言的一个强大特性,允许在运行时检查类的信息并调用私有方法。在连接数据库时,我们可以根据需要连接的...

    java动态代理实现数据库连接池

    频繁地建立和断开数据库连接不仅效率低下,还可能导致性能瓶颈。为了解决这一问题,引入了数据库连接池的概念。连接池能够预先创建并维护一定数量的数据库连接,供应用程序按需使用。尽管市场上存在多种现成的连接池...

    jdbc连接数据库类

    - 在构造函数中,首先通过反射机制加载指定的 JDBC 驱动,然后通过 `DriverManager.getConnection()` 方法创建数据库连接。 - 如果在加载驱动或创建连接过程中出现异常,则捕获异常并输出错误信息“数据库连接失败...

    JAVA反射机制原理剖析配经典例子,以及模拟DBUTIL发射实现的JDBC操作包自己写的一个DEMO.★

    2. **建立数据库连接**:使用`DriverManager.getConnection()`方法,传入数据库URL、用户名和密码,获取`Connection`对象。 3. **预编译SQL语句**:创建`PreparedStatement`对象,通过`Connection.prepareStatement...

    C# SQL Server数据库操作DLL

    1. **数据库连接**:DLL通常会提供一个类,如`DBConnection`,用于管理到SQL Server数据库的连接。这个类可能包含`Open()`、`Close()`方法,以打开和关闭数据库连接,以及`ConnectionString`属性,用于设置连接字符...

    基于Java动态代理和反射机制实现ORM

    接下来,以MySQL数据库为例,我们需要建立一个数据库连接池,如C3P0或HikariCP,以便高效地管理和复用数据库连接。同时,需要设计一个SQL语句生成器,它可以解析实体类和方法参数,生成对应的SQL。 在Windows 10...

    jsp连接数据库的java代码

    通过反射机制实例化指定的数据库驱动类,这是建立数据库连接的前提条件。 ##### 4. 建立连接 ```java public boolean creatConnection() { try { con = DriverManager.getConnection(url, userName, password); ...

    java反射机制的实现与使用

    在Java JDBC中,通常我们会先加载数据库驱动的Class,然后通过反射调用`DriverManager.getConnection()`方法建立数据库连接。 "JspLoginDemo"和"JspLoginDemoByModel1"可能是两个基于JSP的登录示例,其中一个可能...

    JDBC访问数据库步骤

    以下是建立数据库连接的示例代码: * Oracle 数据库(thin 模式):`String url="jdbc:oracle:thin:@localhost:1521:orcl";` * SQL Server 数据库:`String url="jdbc:microsoft:sqlserver://localhost:1433;...

    java连接Oracle数据库详解

    这行代码的作用是通过反射机制加载Oracle JDBC驱动。需要注意的是,如果类路径(classpath)中不存在该驱动程序,则会抛出`ClassNotFoundException`异常。 2. **使用`DriverManager.registerDriver()`方法**: ```...

    java从数据库表反射出实体类,自动生成实体类

    1. **数据库连接**:首先,我们需要建立与数据库的连接。这通常通过JDBC(Java Database Connectivity)来完成。在这个例子中,`DBSession.getConnection()` 方法用于获取数据库连接。 2. **查询元数据**:为了获取...

    java连接sqlserver代码

    在`main`方法中,通过调用`ConnectDB.connect()`方法来尝试建立数据库连接,并根据返回的结果判断连接是否成功: ```java if (ConnectDB.connect() == null) { System.out.println("数据库驱动失败"); } else { ...

    JDBC连接数据库的步骤

    #### 二、建立数据库连接 成功加载驱动后,下一步是使用`DriverManager`类的`getConnection()`方法来建立与数据库的实际连接。这个方法接受三个参数:URL、用户名和密码。URL用于指定数据库的具体位置和类型,格式...

    读取Bean类自动创建数据库

    这通常涉及到Java的反射机制和数据库操作技术。 首先,Java反射机制是Java语言提供的一种强大的功能,允许程序在运行时检查和修改自身的结构和行为。在本场景中,它被用来动态获取Bean类的属性(字段)和方法,这些...

Global site tag (gtag.js) - Google Analytics