Hibernate中获取ID的通用方法

论坛中关联的地址:

http://www.iteye.com/topic/397854

直接上代码比较能说明问题。

首先是一个工具类SpringContextTool.java,getIdValue方法原本其他工具类中的方法,挪过来放在一起说方便。虽然是JDK1.5的编程风格,但是主要技巧同样适用于JDK1.4。

public class SpringContextTool implements ApplicationContextAware {

    /**Spring应用上下文环境*/
    private static ApplicationContext applicationContext;

    /**实现ApplicationContextAware接口的回调方法,设置上下文环境
     * @param applicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextTool.applicationContext = applicationContext;
    }

    public static SessionFactory getSessionFactory() {
        Assert.notNull(applicationContext, "applicationContext is null,请确保spring容器正常启动");
        return (SessionFactory) applicationContext.getBean("sessionFactory");
    }
    
    public static ClassMetadata getClassMetadata(Class<?> cls) {
        return getSessionFactory().getClassMetadata(cls);
    }

    /**得到一个model的id的值,可以直接获得id而不触发sql的产生,适合ManyToOne的场景
     * @param model 有可能是CGLib增强之后的对象
     * @return id
     */
    public static String getIdValue(BaseModel model) {
        if (model instanceof HibernateProxy) {
            return (String) ((HibernateProxy) model).getHibernateLazyInitializer().getIdentifier();
        }
        return (String) getClassMetadata(model.getClass()).getIdentifier(model, EntityMode.POJO);
    }

}

1.这里的applicationContext属性是static的,觉得奇怪吧,没办法啊,为了追求getIdValue是static的,因为Model中或者是BaseModel中实现HashCode或者是equals最好是能调用static的方法,而不是有状态的。

2.getIdValue方法中,参数model可以是Object类型,其中实现方法可以看到,如果是代理对象HibernateProxy,可直接得到他的ID,如果是非代理对象,通过配置信息一样可以得到ID。传入参数可以改成Object类型,返回类型也可以根据需要修改成Object。

下面是我写的BaseModel中的应用(注意hashCode方法的实现,我这里规定ID是String类型的,其他类型的ID一样可以借鉴),仅供参考:

public abstract class BaseModel<E> implements Cloneable, Serializable {
    
    
    public int hashCode() {
        String idStr = SpringContextTool.getIdValue(this);
        return idStr == null ? super.hashCode() : idStr.hashCode();
    }

    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }
        if (other == this) {
            return true;
        }
        /*因为字节码增强的关系,getClass()不能用作判断的依据*/
        if (getClass().getPackage() != other.getClass().getPackage()) {
            return false;
        }
        if (hashCode() == other.hashCode()) {
            return true;
        }
        return false;
    }

    /**日志对象*/
    protected final Logger log = Logger.getLogger(getClass());
    
    
    /**覆盖toString方法,ToStringStyle取值为ToStringStyle.SHORT_PREFIX_STYLE
     * ,调试的时候注意会自动取所有引用的值,会触发所有的Hibernate的延迟加载,
     * 如果遇到性能问题,必须覆盖这个默认的toString方法的实现,或者避免调用这个默认的toString方法。
     * @return String
     */
    public String toString() {
        ToStringBuilder tsb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
        for (Field field : getClass().getDeclaredFields()) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            String name = field.getName();
            if ("log".equals(name) || "serialVersionUID".equals(name)) {
                continue;
            }
            Object obj = ModelUtils.getProperty(this, name);
            if (obj instanceof AbstractPersistentCollection) {
                continue;
            }
            if (obj instanceof Calendar) {
                obj = DateTimeUtils.calendar2StrDateTime((Calendar) obj);
            }
            tsb.append(name, obj);
        }
        return tsb.toString();
    }

    /**提供默认的clone方法的实现,不支持深层复制
     * @return Object
     */
    public E clone() {
        try {
            return (E) super.clone();
        } catch (CloneNotSupportedException ex) {
            throw new IllegalArgumentException(ex.getMessage());
        }
    }
    
    /**提供simple的clone方法的实现,不复制Hibernate代理对象
     * @return Object
     */
    public Object cloneSimple() {
        Object obj = ModelUtils.newInstance(getClass());
        Field[] fields = getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (Modifier.isStatic(fields[i].getModifiers())) {
                continue;
            }
            String name = fields[i].getName();
            if ("serialVersionUID".equals(name)) {
                continue;
            }
            Object fieldObj = ModelUtils.getProperty(this, name);
            if (fieldObj instanceof AbstractPersistentCollection ||
                fieldObj instanceof BaseModel) {
                continue;
            }
            ModelUtils.setProperty(obj, name, fieldObj);
        }
        return obj;
    }

}

相关推荐