Hibernate根据持久化对象获取对应数据库表信息(表名,主键等)
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); } } }