论坛首页 Java企业应用论坛

让你的DBUtils支持enum

浏览 3890 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-09-09   最后修改:2010-09-09

最近几天在研究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());
	}
}
   发表时间: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);
}
...
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics