基于Spring 的 Hibernate5的String 类型与Clob对应(适用于4.x)

来源:互联网 发布:网络大数据查询 编辑:程序博客网 时间:2024/06/06 07:10


转载自:http://www.wangwenhui.com.cn/archives/82



项目现在换成hibernate5后,在原先使用Spring的ClobStringType类型进行String与Clob对应时,无法使用,直接是报空指针异常,经过对Spring源码分析后,发现,ClobStringType是Spring基于hibernate3给出的解决方案,无法支持到hibernate5了,针对这一问题,我参考Spring 的ClobStringType类,自己封装了一个自己的ClobStringType类。下面给出封装的过程,希望对大家能有帮助。

1、先写一个类,继承Hibernate的UserType接口,实现相关的方法,具体如下:



package com.platform.base.usertype;
 
import java.io.Serializable;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
 
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.compare.EqualsHelper;
import org.hibernate.usertype.UserType;
import org.springframework.jdbc.support.lob.LobHandler;
 
import com.platform.common.SpringContextHolder;
 
/**
 * www.wangwenhui.com.cn
 * @ClassName:PtClobTypeString
 * @Description:TODO(实现hibernate中,java String 类对数据库Clob的直接支持类)
 * @Author:王文辉
 * @Date:2016年4月11日
 */
public class PtClobTypeString implements UserType, Serializable {
 
    @Override
    public int[] sqlTypes() {
        return new int[] { Types.CLOB };
    }
 
    @Override
    public Class returnedClass() {
        return String.class;
    }
 
    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return EqualsHelper.equals(x, y);
    }
 
    @Override
    public int hashCode(Object x) throws HibernateException {
        // TODO Auto-generated method stub
        return x.hashCode();
    }
 
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
            throws HibernateException, SQLException {
        if (null != names && names.length > 0) {
            LobHandler lobHandler = getCurrentLobHandler(session);
            return lobHandler.getClobAsString(rs, names[0]);
        }
        return "";
    }
 
    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
            throws HibernateException, SQLException {
 
        LobHandler lobHandler = getCurrentLobHandler(session);
        lobHandler.getLobCreator().setClobAsString(st, index, (String) value);
 
    }
 
    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }
 
    @Override
    public boolean isMutable() {
        // TODO Auto-generated method stub
        return false;
    }
 
    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }
 
    @Override
    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }
 
    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
 
    private LobHandler getCurrentLobHandler(SessionImplementor session) {
        String dialect = session.getFactory().getDialect().getClass().getName();
        if (null != dialect && dialect.toLowerCase().contains("oracle")) {
            return SpringContextHolder.getBean("oracleLobHandler");
        }
        return SpringContextHolder.getBean("defaultLobHandler");
    }
 

}


主要需要实现的方法有两个,一个是,nullSafeGet,用于把clob转换为String类型的实现;另一个是:nullSafeSet,用于把String转换为Clob类型。具体可以根据不同数据库的方法,实现自己的转换函数。我这里使用的还是Spring 的LobHandler这个借口进行转换。

2、配置LobHandler接口,通过spring bean的配置,把LobHandler的两个实现分别注入到Spring 容器中,然后再在上面列出的,根据不同的数据库获取不同的实现进行转换即可。代码如下:

<bean id="nativeJdbcExtractor" lazy-init="true"
        class="org.springframework.jdbc.support.nativejdbc.C3P0NativeJdbcExtractor" />
<bean id="oracleLobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler"
    lazy-init="true">
    <property name="nativeJdbcExtractor">
        <ref bean="nativeJdbcExtractor" />
    </property>
</bean>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"
        lazy-init="true">


3、把我们定义的PtClobTypeString注册成全局定义,如下代码所示:


@TypeDefs({ @TypeDef(name = "ptclobstring", typeClass = PtClobTypeString.class) })


4、hibernate 实体bean的配置使用方式如下:


        /**
     * www.wangwenhui.com.cn
     */
    @Lob
    @Type(type="ptclobstring")
    @Column(name = "plugin_options")
    private String pluginOptions;



附Spring管理bean:

package com.supermap.sgis.util;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;/** * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext. * */public class SpringContextHolder implements ApplicationContextAware {    private static ApplicationContext applicationContext;    /**     * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.     */    public void setApplicationContext(ApplicationContext applicationContext) {        SpringContextHolder.applicationContext = applicationContext; // NOSONAR    }    /**     * 取得存储在静态变量中的ApplicationContext.     */    public static ApplicationContext getApplicationContext() {        checkApplicationContext();        return applicationContext;    }    /**     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.     */    @SuppressWarnings("unchecked")    public static <T> T getBean(String name) {        checkApplicationContext();        return (T) applicationContext.getBean(name);    }    /**     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.     */    @SuppressWarnings("unchecked")    public static <T> T getBean(Class<T> clazz) {        checkApplicationContext();        return (T) applicationContext.getBeansOfType(clazz);    }    /**     * 清除applicationContext静态变量.     */    public static void cleanApplicationContext() {        applicationContext = null;    }    private static void checkApplicationContext() {        if (applicationContext == null) {            throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");        }    }}



原创粉丝点击