Spring3-Hibernate3-jdk7升级Spring4-Hibernate4-jdk8记录

610 阅读2分钟

升级原因


  1. 我司目前的架构是11年左右的架构,目前时间过于久远,且最初的架构人员也已离职。
  2. jdk8从发布到现在也有不少时间了,已经趋于稳定,且提供了很多新特性。
  3. 目前我司准备新起产品线,准备用最新的一些技术,但是老产品的业务功能也不能丢,所以准备给老产品集成Dobbo。以前技术太老,不方便这些组件的扩展。

升级步骤


各种删除,各种替换,这个不多说,说一下注意的点:

  • 一定要引入:classmate.jar,不然会有奇怪的错(没记录了,就不好贴异常栈了)。
  • javassist.jar 如果版本太低,建议升级,否则也会出错
  • jboss-logging.jar 也需要引入,spring3不需要
  • 我用到了redis,所以jedis.jar也顺便升了个级
  • 记得把引入org.springframework.orm.hibernate3下面类的地方都改为:org.springframework.orm.hibernate4

以上相关jar包我都没放版本号,版本请根据自己的spring、hibernate的版本进行下载,maven请无视

升级过程中的坑


  1. jbpm3错误:java.lang.AbstractMethodError: at UserType.nullSafeSet()

    这个问题坑了我不少时间,最后才发现是因为hibernate更新了接口. spring3接口:

    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException 
    

    spring4的接口:

    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException 
    

    可以发现多了个参数。jbpm3实现该方法的类是:

    org.jbpm.db.hibernate.ConverterEnumType
    

    我们重写一下它:

    public class ConverterEnumType implements UserType {
      // 这是spring4的
      @Override
      public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
        return nullSafeGet(rs,names,owner);
      }
    
      // 这是spring4的
      @Override
      public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
        nullSafeSet(st,value,index);
      }
    
      public Object deepCopy(Object o) throws HibernateException { return o; }
      public boolean isMutable() { return false; }
      public Serializable disassemble(Object o) throws HibernateException { return (Serializable) o; }
      public Object assemble(Serializable s, Object o) throws HibernateException { return s; }
      public Object replace(Object original, Object target, Object owner) { return target; }
      public int[] sqlTypes() { return SQLTYPES; }
      public Class returnedClass() { return Converter.class; }
    
      // spring3的
      public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
        String converterDatabaseId = resultSet.getString(names[0]);
        return Converters.getConverterByDatabaseId(converterDatabaseId);
      }
    
      // spring3的
      public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
        String converterDatabaseId = Converters.getConverterId((Converter) value);
        preparedStatement.setString(index, converterDatabaseId);
      }
    }
    
  2. jbpm3的错误:java.lang.NoSuchMethodError: org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session

    这个问题和上面那个问题一样,都是属于hibernate更改了接口,所以我们只需要找到对应的类,重写一下。调用该方法的位置在:

    org.jbpm.persistence.db.DbPersistenceService#getSession
    

    我们来重写一下:

    public class DbPersistenceService implements Service, PersistenceService {
        public Session getSession() {
            if ( (session==null)  && (getSessionFactory()!=null) ) {
              Connection connection = getConnection(false);
              if (isCurrentSessionEnabled) {
                log.debug("using current hibernate session");
                session = getSessionFactory().getCurrentSession();
                mustSessionBeClosed = false;
                mustSessionBeFlushed = false;
                mustConnectionBeClosed = false;
              } else if (connection!=null) {
                log.debug("creating hibernate session with connection "+connection);
                // hibernate4直接就写openSession(),不过可能会造成资源浪费
                session = getSessionFactory().openSession();
                // hibernate3这里可以传一个connection
                //session = getSessionFactory().openSession(connection);
                mustSessionBeClosed = true;
                mustSessionBeFlushed = true;
                mustConnectionBeClosed = false;
              } else {
                log.debug("creating hibernate session");
                session = getSessionFactory().openSession();
                mustSessionBeClosed = true;
                mustSessionBeFlushed = true;
                mustConnectionBeClosed = false;
              }
              
              if (isTransactionEnabled) {
                beginTransaction();
              }
            }
            return session;
          }
    
    }
    

总结


现在还在测试,中途还有很多之前基于spring3做的一些开发需要调整,反正都是坑,


  1. openSession的问题好似有一个更优雅的解决方式
// 还是像spring3一样,根据连接创建session
session = getSessionFactory().withOptions().connection(connection).openSession();