利用cglib給javabean動態添加屬性,不用在建VO

有的時候 好比你用的是hibernate或者Spring jdbc 來作dao層進行數據庫相關的操做的時候,若果是單表的操做的時候 還比較簡單 hibernate可直接返回(get,load)你的須要的po,spring3能夠用rowmapper的實現類來處理這個操做,這些操做對於你們來講都是熟悉的不能在熟悉了。java

、問題:當進行多個表進行鏈接的操做時候,如:node

select p.id,p.name,ad.address,ad.post_code from person p join person_address ad on p.id = ad.person_idspring


如今有兩張表進行查詢 ,查詢出來是兩個表的字段,hibernate中也許你會想建立一個含有這些字段的vo就能夠了解決了 (或者基於這個查詢創建以個視圖 ,而後基於這個視圖在用hibernate進行orm映射,),在spring3裏會用到org.springframework.jdbc.core.BeanPropertyRowMapper如:
this.jdbcTemplate.queryForObject(sql,BeanPropertyRowMapper.newInstance(PersonAdressVo.class));//返回PersonAdressVo對象sql

是的這樣的確能夠解決,想一想若是你的好的查詢,並且結果都不同,鏈接的表也是不少,那麼你建立的vo或者是視圖確定是氾濫的,整個項目就會臃腫起來,這是咱們不想看到的。
、如今說說解決方法:數據庫

你能夠在進行查詢結果的時候,爲你聯合查詢出來的Object 動態添加你查出來的屬性;app

下面來講一下具體的代碼:ide

此時須要你須要cglib-nodep-2.2.jar,本身google下載post

DynamicBean.java測試

package com.ajun.spring.orm;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;

/**
*
* @author ajun
*
*/
public class DynamicBean {

/**
* 實體Object
*/
private Object object = null;

/**
* 屬性map
*/
private BeanMap beanMap = null;

public DynamicBean() {
super();
}

@SuppressWarnings("unchecked")
public DynamicBean(Map propertyMap) {
this.object = generateBean(propertyMap);
this.beanMap = BeanMap.create(this.object);
}

/**
* 給bean屬性賦值
* @param property 屬性名
* @param value 值
*/
public void setValue(String property, Object value) {
beanMap.put(property, value);
}

/**
* 經過屬性名獲得屬性值
* @param property 屬性名
* @return 值
*/
public Object getValue(String property) {
return beanMap.get(property);
}

/**
* 獲得該實體bean對象
* @return
*/
public Object getObject() {
return this.object;
}

/**
* @param propertyMap
* @return
*/
@SuppressWarnings("unchecked")
private Object generateBean(Map propertyMap) {
BeanGenerator generator = new BeanGenerator();
Set keySet = propertyMap.keySet();
for (Iterator i = keySet.iterator(); i.hasNext();) {
String key = (String) i.next();
generator.addProperty(key, (Class) propertyMap.get(key));
}
return generator.create();
}

}this

測試類:

public static void main(String[] args) throws ClassNotFoundException {

// 設置類成員屬性
HashMap propertyMap = new HashMap();

propertyMap.put("id", Class.forName("java.lang.Integer"));

propertyMap.put("name", Class.forName("java.lang.String"));

propertyMap.put("address", Class.forName("java.lang.String"));

// 生成動態 Bean
DynamicBean bean = new DynamicBean(propertyMap);

// 給 Bean 設置值
bean.setValue("id", new Integer(123));

bean.setValue("name", "454");

bean.setValue("address", "789");

// 從 Bean 中獲取值,固然了得到值的類型是 Object

System.out.println(" >> id = " + bean.getValue("id"));

System.out.println(" >> name = " + bean.getValue("name"));

System.out.println(" >> address = " + bean.getValue("address"));

// 得到bean的實體
Object object = bean.getObject();

// 經過反射查看全部方法名
Class clazz = object.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i].getName());
}
}

在這裏在舉一個spring jdbc中查詢多個表 ,返回一個動態bean的例子:
首先是你在用spring3 jdbc進行查詢的時候 這時候你想返回一個對象 此時你通常的作法是:

String sql="select p.id,p.name,ad.address,ad.post_code from person p join person_address ad on p.id = ad.person_id";//此時你返回是多個表的結果
this.jdbcTemplate.queryForObject(sql,BeanPropertyRowMapper.newInstance(PersonAddressVO.class), id);//返回一個含有多個表的屬性的vo:PersonAddressVO
隨着你的業務的複雜也許你vo會不少 ,爲了減小你vo的數量 ,應該動態返回一個bean 此時bean含有你想要的的屬性。
咱們在用spring jdbc 進行查詢 就行orm映射的時候 都要是首先實現org.springframework.jdbc.core.RowMapper,由於spring jdbc查詢的時候你要進行orm要求一個參數必須爲org.springframework.jdbc.core.RowMapper,因此此時我要實現org.springframework.jdbc.core.RowMapper裏的public Object mapRow(ResultSet rs, int rowNum) f。

裏面咱們會用前面的DynamicBean.java

package com.ajun.spring.orm;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;



/**
*********************************************************************************
* 例子:數據庫:person_id <----->po:personId 請寫好駝峯表示風格
*********************************************************************************
* @author ajun
*/
@SuppressWarnings("unchecked")
public class CustomRowMapper implements RowMapper {


@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return this.toDynamicObject(rs, rowNum);
}

private Object toDynamicObject(ResultSet rs, int rowNum) throws SQLException{
DynamicBean dyBean =null;
ResultSetMetaData rsmd = rs.getMetaData();
if(rsmd!=null){
int columnCount = rsmd.getColumnCount();
HashMap propertyMap = new HashMap();
for (int index = 1; index <= columnCount; index++){//JdbcUtils本身查spring API
String column = JdbcUtils.lookupColumnName(rsmd, index);
String propertyName = JdbcUtils.convertUnderscoreNameToPropertyName(column);
propertyMap.put(propertyName, Object.class);//添加動態屬性 此時person_address ==>personAddress
}
dyBean = new DynamicBean(propertyMap);
for (int index = 1; index <= columnCount; index++){
String column = JdbcUtils.lookupColumnName(rsmd, index);
String propertyName = JdbcUtils.convertUnderscoreNameToPropertyName(column);
Object value = JdbcUtils.getResultSetValue(rs, index);
dyBean.setValue(propertyName, value);//設置值
}
}
return dyBean.getObject();
}


public static CopyOfCustomRowMapper newInstance() {
CopyOfCustomRowMapper newInstance = new CopyOfCustomRowMapper();
return newInstance;
}

}
調用的時候:
String sql="select p.id,p.name,ad.address,ad.post_code from person p join person_address ad on p.id = ad.person_id";//此時你返回是多個表的結果
List<Object> list = this.jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance());//返回一個含有多個表的屬性的動態bean

在頁面上你就能夠用el表達式這樣去出來:<c:forEach items="${list}" var="p"> <tr> <td>${p.id}</td> <td>${p.name}</td> <td>${p.address}</td> <td>${p.postCode}</td></tr> </c:forEach>

相關文章
相關標籤/搜索