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


转载自: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");
        }
    }
}



猜你喜欢

转载自blog.csdn.net/u010299087/article/details/76019094