`
jwinder
  • 浏览: 27234 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

让你的DBUtils支持enum

    博客分类:
  • JAVA
阅读更多

最近几天在研究Java分布式技术如:Socket、Mina、Web Service、Hessian、REST等。

今天早上看到DBUtils,试用了起来,并写了测试单元。

 

1、创建了一个日志表,用DBUtils读写日志,然后进行了测试,在测试过程中,发现

new BeanHandler<ActionLog>(ActionLog.class)

 这个过程中出现有些数据为空 ,仔细一看数据库字段,如:log_id,log_tag有下划线的都取不出数据来 。然后google了一下发现JE里有个文章正好解决了这个问题:http://www.iteye.com/topic/381714

 

2、根据文章说的在 org.apache.commons.dbutils.BeanProcessor 添加了个方法columnPropEquals(表字段和类属性比较)

    private boolean columnPropEquals(String columnName, String propName) {
   {
          return (columnName.replace("_", "").equalsIgnoreCase(propName.replace("_", "")));
   }}

    并且在mapColumnsToProperties 中调用些方法

    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
            PropertyDescriptor[] props) throws SQLException {

        int cols = rsmd.getColumnCount();
        int columnToProperty[] = new int[cols + 1];
        Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);

        for (int col = 1; col <= cols; col++) {
            String columnName = rsmd.getColumnLabel(col);
            
            if (null == columnName || 0 == columnName.length()) {
              columnName = rsmd.getColumnName(col);
            }
            
            for (int i = 0; i < props.length; i++) {
            	//在这里进行调用新的比较方法
                if (columnPropEquals(columnName, props[i].getName())) {
                    columnToProperty[col] = i;
                    break;
                }
            }
        }

        return columnToProperty;
    }
 

 3、继续跑单元测试,然后又报错

Exception in thread "main" java.sql.SQLException Cannot set  logType: incompatible types.

 然后我用DEBUG跟踪后发现是数据类型 的问题,BeanProcessor.callSetter 无法把Object 转成Enum类型

// Don't call setter if the value object isn't the right type 
            if (this.isCompatibleType(value, params[0])) {
                setter.invoke(target, new Object[] { value });
            }

 

4、找到BeanProcessor.callSetter 方法,在[3]中的if后面 添加了特有Enum类型的值设置

// Don't call setter if the value object isn't the right type 
            if (this.isCompatibleType(value, params[0])) {
                setter.invoke(target, new Object[] { value });
            }
            else if (params[0].isEnum())
            {
            	try {
            		//value == null时,让Domain设置默认值
            		//只有value != null时对进行转换设置值
            		if(value != null)
            		{
            			//Class转换对应enum
                		Class cz = Class.forName(params[0].getName());
    					setter.invoke(target, Enum.valueOf(cz, (String) value));
            		}
				} catch (ClassNotFoundException e) {
					throw new SQLException("Cannot set " + prop.getName() + ": incompatible types.");
				}
				
            }

 5、继续跑单元测试,成功

  ActionLog [logContent=测试, logId=1, logLevel=INFO, logSourceId=, logTag=测试, logType=ACTION, opdate=2010-09-08 05:53:22.0, opip=192.168.1.159, opuser=JWinder]

 

6、总结

有的时候发现很多开源的项目并没有我们想像得那么完美,当你发现不完美(缺陷)时,修正它,并把你的经验分享给每一个人,让别人站在你的时间上节约时间,所以希望大家一起分享你的快乐

 

 

 

7、附件,附上我的ActionLog和单元测试

ActionLog.java

public class ActionLog implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private Long     logId;                     // 日志ID
	private LogType  logType = LogType.NORMAL;  // 日志类型
	private LogLevel logLevel = LogLevel.INFO;	// 事件级别
	private String   opuser;				    // 操作人ID
	private Date     opdate;                    // 操作时间
	private String   opip;                      // 操作IP
	private String   logSourceId;			    // 操作关联源对象ID
	private String   logTag;                    // 操作事件内容标签(提供更好的搜索)
	private String   logContent;                // 事件内容
	
	public enum LogType {
		/** 一般日志 */
		NORMAL("NORMAL"),
		
		/** 登录日志 */
		LOGIN("LOGIN"),
		
		/** 活动操作日志 */
		ACTION("ACTION"),
		
		/** 错误日志 */
		ERROR("ERROR"),
		;
		
		private String name;

		LogType(String name) {
			this.name = name;
		}
	
		public String getName() {
			return this.name;
		}
		
	}

	public enum LogLevel {
		
		INFO("INFO"),
		
		SUCCESS("SUCCESS"),
		
		WARN("WARN"),
		
		ERROR("ERROR"),
		
		;
		
		private String name;

		LogLevel(String name) {
			this.name = name;
		}
	
		public String getName() {
			return this.name;
		}
	}

	public Long getLogId() {
		return logId;
	}

	public void setLogId(Long logId) {
		this.logId = logId;
	}

	public LogType getLogType() {
		return logType;
	}

	public void setLogType(LogType logType) {
		this.logType = logType;
	}

	public LogLevel getLogLevel() {
		return logLevel;
	}

	public void setLogLevel(LogLevel logLevel) {
		this.logLevel = logLevel;
	}

	public String getOpuser() {
		return opuser;
	}

	public void setOpuser(String opuser) {
		this.opuser = opuser;
	}

	public Date getOpdate() {
		return opdate;
	}

	public void setOpdate(Date opdate) {
		this.opdate = opdate;
	}

	public String getOpip() {
		return opip;
	}

	public void setOpip(String opip) {
		this.opip = opip;
	}

	public String getLogSourceId() {
		return logSourceId;
	}

	public void setLogSourceId(String logSourceId) {
		this.logSourceId = logSourceId;
	}

	public String getLogTag() {
		return logTag;
	}

	public void setLogTag(String logTag) {
		this.logTag = logTag;
	}

	public String getLogContent() {
		return logContent;
	}

	public void setLogContent(String logContent) {
		this.logContent = logContent;
	}

	@Override
	public String toString() {
		return "ActionLog [logContent=" + logContent + ", logId=" + logId
				+ ", logLevel=" + logLevel + ", logSourceId=" + logSourceId
				+ ", logTag=" + logTag + ", logType=" + logType + ", opdate="
				+ opdate + ", opip=" + opip + ", opuser=" + opuser + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((logId == null) ? 0 : logId.hashCode());
		result = prime * result
				+ ((logLevel == null) ? 0 : logLevel.hashCode());
		result = prime * result + ((logType == null) ? 0 : logType.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ActionLog other = (ActionLog) obj;
		if (logId == null) {
			if (other.logId != null)
				return false;
		} else if (!logId.equals(other.logId))
			return false;
		if (logLevel == null) {
			if (other.logLevel != null)
				return false;
		} else if (!logLevel.equals(other.logLevel))
			return false;
		if (logType == null) {
			if (other.logType != null)
				return false;
		} else if (!logType.equals(other.logType))
			return false;
		return true;
	}
	
	public static String getInsertSQL()
	{
		return ("INSERT INTO action_log (log_type, log_level, opuser, opdate, opip, log_source_id, log_tag, log_content) values (?, ?, ?, ?, ?, ?, ?, ?)");
	}
	
	public static Object[] toArray(ActionLog log)
	{
		return new Object[] {log.logType, log.logLevel, log.opuser, log.opdate, log.opip, log.logSourceId, log.logTag, log.logContent};
	}
	
	public static ActionLog getTestActionLog()
	{
		ActionLog log = new ActionLog();
		log.setLogType(LogType.ACTION);
		log.setLogLevel(LogLevel.INFO);
		log.setOpuser("JWinder");
		log.setOpdate(new Date());
		log.setOpip("192.168.1.159");
		log.setLogSourceId("");
		log.setLogTag("测试 操作日志");
		log.setLogContent("测试日志系统数据");
		return log;
	}
	
	public static void main(String[] args) {
		System.err.println(LogType.ACTION);
	}
	
}

 action_log表SQL

 create database logservice;
    use logservice;

	drop table `logservice`.`action_log`;
	
    create table `logservice`.`action_log`(
        `log_id` INT not null auto_increment,
       `log_type` VARCHAR(16) not null,
       `log_level` VARCHAR(16) not null,
       `opuser` VARCHAR(32) not null,
       `opdate` DATETIME not null,
       `opip` VARCHAR(32) not null,
       `log_source_id` VARCHAR(64),
       `log_tag` VARCHAR(256),
       `log_content` TEXT not null,
        primary key (`log_id`)
    );

 

DBUtilsTest.java

public class DBUtilsTest {
	
	public static void main(String[] args) throws SQLException, ClassNotFoundException {
//		Connection conn = null;  
//        Statement stmt = null;  
//        ResultSet rs = null;  
//        Class.forName("com.mysql.jdbc.Driver");
//        conn = DriverManager.getConnection("jdbc:mysql://192.168.1.82:3306/logservice", "root", "123456");  
//            stmt = conn.createStatement();  
//            stmt.executeUpdate("INSERT INTO action_log (log_type, log_level, opuser, opdate, opip, log_source_id, log_tag, log_content) values " +
//            		"('ACTION', 'INFO', 'JWinder','2010-09-08 05:53:22.123', '192.168.1.159', '', '测试 操作日志', '测试日志系统数据')");
            
		DBUtilsTest example = new DBUtilsTest();
		//example.batch();
		//example.fillStatement();
		//example.query();
		//example.update();
		example.qq();
		example.closeDataSource();
	}

	private DataSource dataSource = null;
	private QueryRunner runner = null;

	public DBUtilsTest() {
		initDataSource();
		runner = new QueryRunner(dataSource);
	}

	private void closeDataSource() throws SQLException {
		((BasicDataSource) dataSource).close();
	}
	private DataSource initDataSource() {
		if (dataSource == null) {
			BasicDataSource basicDs = new BasicDataSource();
			basicDs.setDriverClassName("com.mysql.jdbc.Driver");
			basicDs.setUrl("jdbc:mysql://192.168.1.82:3306/logservice");
			basicDs.setUsername("root");
			basicDs.setPassword("123456");
			this.dataSource = basicDs;
		}
		return dataSource;
	}

	private void qq() throws SQLException
	{
		String sql = "SELECT * FROM action_log WHERE log_id = ?";
		ActionLog r4 = runner.query(sql, new BeanHandler<ActionLog>(ActionLog.class), "1");
		System.out.println("  " + r4.toString());
	}
}
分享到:
评论
1 楼 caowuhui 2010-12-31  
yes,的确如此,另外它好像对成员变量的类型为java.util.Date的字段也不能转换,所以我改了它的processColumn(ResultSet rs, int index,Class<?> propType)方法:

...
else if (propType.equals(Timestamp.class)) {
    return rs.getTimestamp(index);
}
...
改为了
...
else if (propType.equals(java.util.Date.class) || propType.equals(Timestamp.class)) { //变动
     return rs.getTimestamp(index);

} else if (propType.equals(java.sql.Date.class)) { //变动
     return rs.getDate(index);

} else if (propType.equals(java.sql.Time.class)) { //变动
     return rs.getTime(index);
}
...

相关推荐

    dbutils dbutils dbutils dbutils

    DBUtils 是一个非常重要的 Python 模块,专为数据库连接设计,它在 Python 的数据库应用开发中扮演着不可或缺的角色。这个模块主要目的是提供一...在进行数据库相关的开发工作时,DBUtils 应该是你的首选辅助工具之一。

    DBUtils操作数据库以及事物的管理

    在DBUtils中,可以通过控制`Connection`对象的自动提交属性来实现对事务的支持。 1. **开启事务**: - 获取`Connection`对象并关闭自动提交。 ```java Connection conn = JdbcUtils.getConnection(); conn....

    python的DBUtils包

    - 假设你在Anaconda环境下工作,你需要将`DBUtils`目录复制到`anaconda\lib\site-packages`路径下。 - 这样,DBUtils就被添加到了你的Python环境中。你可以在Python console中输入`import DBUtils`,如果没有出现...

    模仿DBUtils(自己模仿DBUtils写的简易DBUtils)

    这个模仿版本也应该做到了这一点,让你的代码更专注于业务逻辑而不是数据库细节。 通过学习和实践这个简易DBUtils,你将深入理解数据库连接池的工作原理,掌握PreparedStatement的使用,熟悉数据库事务管理,以及...

    Dbutils 的jar包

    QueryRunner支持预编译的PreparedStatement,能有效防止SQL注入攻击。 2. **ResultSetHandler**:这个接口用于处理查询结果集。Dbutils 提供了几种常见的实现,如 `ArrayListHandler`(将结果集转换为 List), `...

    DBUtils数据库的使用

    4. **ConnectionPool**:DBUtils支持数据库连接池,如DBCP、C3P0等,以提高数据库操作的性能。连接池可以有效地管理数据库连接,避免了频繁创建和关闭连接的开销。 5. **ExceptionTranslator**:DBUtils包含了对...

    commons-dbutils-1.4.jar

    这个项目的最新版本为"commons-dbutils-1.4.jar",它的主要目标是减轻开发人员在处理数据库连接、查询结果集等方面的负担,让Java程序员能够更加专注于业务逻辑,而不是底层的数据库交互细节。 DBUtils的核心设计...

    commons-dbutils.jar.rar

    它支持预编译的PreparedStatement以及批处理操作,可以有效地防止SQL注入攻击。 - **ResultSetHandler**: 提供了一系列预定义的处理结果集的接口和实现,如ListHandler、BeanHandler、ArrayHandler等,可以直接将...

    commons-dbutils-1.7

    Apache Commons DbUtils是Java开发中的一个实用工具库,专门针对JDBC...总的来说,Apache Commons DbUtils是Java开发中一个非常实用的工具,它通过简化JDBC编程,让开发者能够专注于业务逻辑,而不是数据库交互的细节。

    DButils使用实例

    DButils支持多种数据库连接池,如C3P0、DBCP、HikariCP等。连接池是数据库管理的关键组件,它能够有效地重用数据库连接,减少创建和销毁连接的开销,提高系统性能。通过DButils,开发者可以轻松配置和使用这些连接...

    DbUtils数据库查询工具包 v1.8.1.zip

    DbUtils是Apache组织提供的...在毕业设计论文或计算机案例中,使用DbUtils进行数据库操作能让你的项目看起来更专业、更规范。模板建站和系统软件工具也可以利用DbUtils简化数据库操作部分,使代码更加简洁和易于维护。

    dbutils

    1. **批处理操作**:`dbutils` 支持批量执行SQL语句,可以显著提高数据库操作的性能,尤其在处理大量数据时。 2. **QueryRunner与ResultSetHandler**:`QueryRunner` 类是`dbutils` 的核心组件,它提供了一种简单的...

    DButils 的源代码

    在这个场景中,你提到的是 DButils 源码与 HSQldb 版本 2.0.0 的结合,这可能意味着你正在研究或分析这两个组件如何协同工作。 DButils 的核心功能主要包括以下几点: 1. **连接池管理**:DButils 提供了连接池的...

    commons-dbutils-1.3.zip

    这些方法支持预编译的PreparedStatement,增强了安全性,防止SQL注入攻击。 2. **ResultSetHandler接口**:处理查询结果集的关键接口。开发者可以实现这个接口来定义如何处理查询返回的结果。DBUtils已经提供了一些...

    C3P0和DButils

    DBUtils的核心功能包括QueryRunner类,它支持预编译的SQL语句,可以有效防止SQL注入攻击。此外,DBUtils还提供了异常处理机制,使得数据库操作更加健壮。 将C3P0和DBUtils结合使用,可以构建一个高效且稳定的数据库...

    DBUtils数据库工具类

    1. **连接池管理**:DBUtils支持多种连接池实现,如C3P0、DBCP和HikariCP等。通过配置文件,开发者可以轻松设置连接池参数,实现数据库连接的复用,降低系统资源消耗。 2. **QueryRunner**:QueryRunner是DBUtils的...

    python类DBUtils安装包

    DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块。DBUtils已经作为 Webware for Python 一部分用来结合 PyGreSQL 访问 PostgreSQL 数据库,当然他也可以用在其他Python应用程序中来访问 DB-...

    DbUtils的Jar包

    3. **SQL执行**:DbUtils的`QueryRunner`类提供了执行SQL查询和更新操作的方法,支持预编译的PreparedStatement,增强了SQL语句的安全性,防止SQL注入攻击。例如,`QueryRunner.query()`方法用于执行查询,`Query...

    dbutils api

    - **文件系统操作**: `dbutils.fs` 命名空间提供了对分布式文件系统的访问,支持HDFS、S3等存储服务。通过这个API,可以进行创建、读取、删除、移动文件或目录等操作。 - **变量管理**: `dbutils.widgets` 提供了在...

Global site tag (gtag.js) - Google Analytics