Hibernate根据持久化对象获取对应数据库表信息(表名,主键等)
这几天要写个DAO层自动记录数据库操作日志的功能,兼容Hibernate及JDBC。
Hibernate开发中需要根据持久层对象获取所映射的数据库表相关信息,如表名,主键,外键对象等相关系。
一、核心的几个方法如下:
获取对象映射缓存管理类
AbstractEntityPersister classMetadata = (AbstractEntityPersister)super.getSessionFactory().getClassMetadata(object.getClass());
//表名
String tableName = classMetadata.getTableName();
//对象名称
String entityName = classMetadata.getEntityName();
//主键列映射属性
String pkPropertyName = classMetadata.getIdentifierPropertyName();
//数据库主键列
String[] pkColumns = classMetadata.getIdentifierColumnNames();
//反射调用获取主键值
String pkPropertyValue = BeanUtils.getProperty(object, pkPropertyName);
hibernate自带反射取值函数
classMetadata.getPropertyValue(object, propertyName, org.hibernate.EntityMode.POJO);
非主键属性
String[] propertyNames = classMetadata.getPropertyNames();
非主键数据库列
String[] propertyColumns = classMetadata.getPropertyColumnNames(propertyName);
非主键属性是否可修改bool值有序集合
boolean[] isUpdateFalgs = classMetadata.getPropertyUpdateability();
非主键属性是否可添加bool值有序集合
boolean[] isInsertFlags = classMetadata.getPropertyInsertability();
获取属性数据类型
Type propertyType = classMetadata.getPropertyType(pkPropertyName)
是否是集合类型
propertyType.isCollectionType()
是否是对象类型
propertyType.isEntityType()
是否是时间类型
propertyType instanceof DateType
获取外键对象
Object fkObj = classMetadata.getPropertyValue(object, propertyName, org.hibernate.EntityMode.POJO);
二、下边是日志记录的核心代码块:
/**
* @Description: 初始化
* @param sessionFactory
* @param object
*/
public HibernateResourceLog(SessionFactory sessionFactory, Object object)
{
HibernateResourceLog.sessionFactory = sessionFactory;
this.object = object;
super.dbInfoBean = getTableInfoByObj();
}
/**
* @Description: 设置操作后信息(事务管理)
* @author: wubin
* @return
* @date: 2012-9-27
*/
@Override
public DBInfoBean setNextInfo()
{
// 事务管理
// 1.获取数据库字段, 并生成Map对象
LinkedHashMap<String, Object> nextInfoMap = new LinkedHashMap<String, Object>();
Object[] colNames = new Object[0];
if(!dbInfoBean.getOperateType().equals(BusinessConstants.RESOURCE_OPERATE_TYPE_INSERT))
{
colNames = dbInfoBean.getPreInfo().keySet().toArray();
for(int i = 0; i < colNames.length; i++)
{
nextInfoMap.put(String.valueOf(colNames[i]), "");
}
}
try {
// 2.根据字段查询Hibernate中对应属性
AbstractEntityPersister classMetadata = (AbstractEntityPersister)sessionFactory.getClassMetadata(object.getClass());
// 3.主键填值
// 3.1获取主键列映射属性
String pkPropertyName = classMetadata.getIdentifierPropertyName();
// 3.2非集合类属性
if(!classMetadata.getPropertyType(pkPropertyName).isCollectionType())
{
//3.3 获取数据库主键列
String[] pkColumns = classMetadata.getIdentifierColumnNames();
//3.4 反射调用获取主键值
String pkPropertyValue = BeanUtils.getProperty(object, pkPropertyName);
nextInfoMap.put(pkColumns[0], pkPropertyValue);
}
// 4.非主键填值
String[] propertyNames = classMetadata.getPropertyNames();
boolean[] isUpdateFalgs = classMetadata.getPropertyUpdateability();
boolean[] isInsertFlags = classMetadata.getPropertyInsertability();
for(int i = 0; i < propertyNames.length; i++)
{
String propertyName = propertyNames[i];
String[] propertyColumns = classMetadata.getPropertyColumnNames(propertyName);
// 如果需要更新或添加则判断数据类型获取对象属性,否则设置标志,为后续日志记录做准备
if((!isUpdateFalgs[i] || !isInsertFlags[i])
&& !dbInfoBean.getOperateType().equals(BusinessConstants.RESOURCE_OPERATE_TYPE_INSERT))
{
nextInfoMap.put(propertyColumns[0], dbInfoBean.getPreInfo().get(propertyColumns[0]));
}
else
{
parseObjectCache(nextInfoMap, propertyName);
}
}
} catch (IllegalAccessException e) {
logger.error(e);
} catch (InvocationTargetException e) {
logger.error(e);
} catch (NoSuchMethodException e) {
logger.error(e);
}
dbInfoBean.setNextInfo(nextInfoMap);
return dbInfoBean;
}
/**
* @Description: 获取对象对应数据库表信息
* @author: wubin
* @return
* @date: 2012-9-27
*/
private DBInfoBean getTableInfoByObj() {
// SessionFactory获取持久对象表信息对象
AbstractEntityPersister classMetadata = (AbstractEntityPersister)sessionFactory.getClassMetadata(object.getClass());
DBInfoBean dbInfoBean = new DBInfoBean();
// 获取表名
dbInfoBean.setTableName(classMetadata.getTableName());
// 获取主键列映射属性
String pkPropertyName = classMetadata.getIdentifierPropertyName();
// 非集合类属性
if(!classMetadata.getPropertyType(pkPropertyName).isCollectionType())
{
// 获取数据库主键列
String[] pkColumns = classMetadata.getIdentifierColumnNames();
dbInfoBean.setPkColumns(pkColumns);
// 反射调用获取主键值
String pkPropertyValue = "";
try {
pkPropertyValue = BeanUtils.getProperty(object, pkPropertyName);
} catch (IllegalAccessException e) {
logger.error(e);
} catch (InvocationTargetException e) {
logger.error(e);
} catch (NoSuchMethodException e) {
logger.error(e);
}
String[] pkPropertyValues = new String[]{pkPropertyValue};
dbInfoBean.setPkColumnsValue(pkPropertyValues);
}
else
{
return null;
}
return dbInfoBean;
}
/**
* @Description: 将对象缓存属性转换成Map对象
* @author: wubin
* @param nextInfoMap
* @param propertyName
* @param classMetadata
* @param object
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @date: 2012-9-27
*/
private void parseObjectCache(LinkedHashMap<String, Object> nextInfoMap, String propertyName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
AbstractEntityPersister classMetadata = (AbstractEntityPersister)sessionFactory.getClassMetadata(object.getClass());
String[] propertyColumns = classMetadata.getPropertyColumnNames(propertyName);
Type propertyType = classMetadata.getPropertyType(propertyName);
// 4.1 对象属性取外键对象主键值
if(propertyType.isEntityType())
{
// 获取外键对象
Object fkObj = classMetadata.getPropertyValue(object, propertyName, org.hibernate.EntityMode.POJO);
AbstractEntityPersister fKclassMetadata = (AbstractEntityPersister)sessionFactory.getClassMetadata(fkObj.getClass());
// 获取主键属性
String fKPkPropertyName = fKclassMetadata.getIdentifierPropertyName();
if(propertyColumns.length > 0)
{
// 获取主键列值
String fkPkPropertyValue = BeanUtils.getProperty(fkObj, fKPkPropertyName);
nextInfoMap.put(propertyColumns[0], fkPkPropertyValue);
}
}
else if(propertyType.isCollectionType())
{
// 4.2 赞不考虑主键为集合属性,复合主键后期统一修改
}
else if (propertyType instanceof DateType) {
// 4.3 时间类型需转换
Date date = (Date)classMetadata.getPropertyValue(object, propertyName, org.hibernate.EntityMode.POJO);
String dateStr = DateUtil.getDateTime(date);
if(propertyColumns.length > 0)
{
nextInfoMap.put(propertyColumns[0], dateStr);
}
}
else
{
// 4.3 字符串等普通类型直接取值
String propertyValue = BeanUtils.getProperty(object, propertyName);
if(propertyColumns.length > 0)
{
nextInfoMap.put(propertyColumns[0], propertyValue);
}
}
}