Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使Hibernate使用setFixedCHAR而不是setString_String_Hibernate_Spring Data Jpa_Parameterbinding - Fatal编程技术网

如何使Hibernate使用setFixedCHAR而不是setString

如何使Hibernate使用setFixedCHAR而不是setString,string,hibernate,spring-data-jpa,parameterbinding,String,Hibernate,Spring Data Jpa,Parameterbinding,我是否可以修改Hibernate将参数绑定到查询的方式 例如,我希望hibernate在字符串列上执行时使用OracleResultSet.setFixedChar(),而不是在通过Spring数据执行JPA查询时使用rs.setString() 如果没有Hibernate,我会这样做: try(PreparedStatement ps = con.executeQuery("...")) { if(ps.isWrapped(OraclePreparedStatement.class) {

我是否可以修改Hibernate将参数绑定到查询的方式

例如,我希望hibernate在字符串列上执行时使用
OracleResultSet.setFixedChar()
,而不是在通过Spring数据执行JPA查询时使用
rs.setString()

如果没有Hibernate,我会这样做:

try(PreparedStatement ps = con.executeQuery("...")) {
   if(ps.isWrapped(OraclePreparedStatement.class) {
      ps.unwrap(OraclePreparedStatement.class).setFixedCHAR(0, myStringField);
   } else {
      ps.setString(0, myStringField);
   }

   try(ResultSet rs = ps.getResultSet()) {
      while(rs.next()) {
         ... do stuff ...
      }
   }
}
存储库方法(Spring数据JPA):

List findByMyStringField(字符串myStringField);
如何影响Hibernate绑定变量的方式。在上述示例中,始终使用
setString


背景:问题是我们所有的遗留数据库都使用
CHAR
列,而不是
VARCHAR2
,因此我们必须处理空白,并且
setFixedCHAR
应该完全按照我们的要求来做。

通过实现SqlTypeDescriptor和自定义方言找到了解决方案:

  @Autowired
  private DataSource source;

  @Bean
  public HibernateJpaVendorAdapter getHibernateJPAVendorAdapter() {
    return new CustomHibernateJpaVendorAdaptor();
  }

  private static class CustomHibernateJpaVendorAdaptor extends HibernateJpaVendorAdapter {

    @Override
    protected Class<?> determineDatabaseDialectClass(Database database) {
      // if HSQL is copied from Spring Sourcecode to keep everything the same
      if (Database.HSQL.equals(database)) {
        return CustomHsqlDialect.class;
      }
      try {
        if (source.isWrapperFor(OracleDataSource.class)) {
          return CustomOracleDialect.class;
        }
      } catch (SQLException e) {
      }
      return super.determineDatabaseDialectClass(database);
    }

    private class CustomHsqlDialect extends HSQLDialect {

      public CustomHsqlDialect() {
        registerColumnType(Types.BOOLEAN, "boolean");
        registerHibernateType(Types.BOOLEAN, "boolean");
      }
    }
  }

  @NoArgsConstructor
  public static class CustomOracleDialect extends Oracle12cDialect {

    private static final OracleCharFix INSTANCE = new OracleCharFix();


    @Override
    protected SqlTypeDescriptor getSqlTypeDescriptorOverride(final int sqlCode) {
      switch (sqlCode) {
        case Types.VARCHAR:
          return INSTANCE;
        default:
          return super.getSqlTypeDescriptorOverride(sqlCode);
      }
    }
  }

  @Slf4j
  private static class OracleCharFix extends CharTypeDescriptor {

    @Override
    public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
      return new BasicBinder<>(javaTypeDescriptor, this) {
        @Override
        protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
          throws SQLException {
          if (st.isWrapperFor(OraclePreparedStatement.class)) {
            OraclePreparedStatement ops = st.unwrap(OraclePreparedStatement.class);
            if (ops.getParameterMetaData().getParameterType(index) == Types.CHAR) {
              ops.setFixedCHAR(index, javaTypeDescriptor.unwrap(value, String.class, options));
            } else {
              st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
            }
          } else {
            st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
          }
        }

        @Override
        protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
          throws SQLException {
            //Is nolonger used by Hibernate in the current Version
            st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
        }

        private boolean checkIfCHARByName(ResultSetMetaData metadata, String name)
          throws SQLException {
          for (int i = 1; i <= metadata.getColumnCount(); i++) {
            if (metadata.getColumnType(i) == Types.CHAR && Objects.equals(metadata.getColumnName(i), name)) {
              return true;
            }
          }
          return false;
        }
      };
    }
@Autowired
私有数据源;
@豆子
公共hibernatejbavendorapter gethibernatejbavendorapter(){
返回新的CustomHibernateJavaEndoraptor();
}
私有静态类CustomHibernateJavaEndoRadaptor扩展了HibernateJavaEndoRadapter{
@凌驾
已确定的受保护类DatabaseDiagnolClass(数据库){
//如果HSQL是从Spring源代码复制的,则保持一切不变
if(Database.HSQL.equals(Database)){
返回customhsqldialine.class;
}
试一试{
if(source.isWrapperFor(OracleDataSource.class)){
返回CustomOracleDialogue.class;
}
}捕获(SQLE异常){
}
返回super.determinedatabasediallationclass(数据库);
}
私有类customHSQLdialent扩展了HSQLdialent{
公共customhsqldialine(){
registerColumnType(Types.BOOLEAN,“BOOLEAN”);
registerHibernateType(Types.BOOLEAN,“BOOLEAN”);
}
}
}
@诺尔格构装师
公共静态类CustomOracleDialogue扩展了Oracle12cDialect{
私有静态最终OracleCharFix实例=新OracleCharFix();
@凌驾
受保护的SqlTypeDescriptor getSqlTypeDescriptorOverride(最终int-sqlCode){
开关(sqlCode){
case Types.VARCHAR:
返回实例;
违约:
返回super.getsqltypedescriptorverride(sqlCode);
}
}
}
@Slf4j
私有静态类OracleCharFix扩展了CharTypeDescriptor{
@凌驾
public ValueBinder getBinder(最终JavaTypeDescriptor JavaTypeDescriptor){
返回新的BasicBinder(javaTypeDescriptor,this){
@凌驾
受保护的void doBind(PreparedStatement st、X值、int索引、包装器选项)
抛出SQLException{
if(st.isWrapperFor(OraclePreparedStatement.class)){
OraclePreparedStatement ops=st.unwrap(OraclePreparedStatement.class);
if(ops.getParameterMetaData().getParameterType(index)=Types.CHAR){
setFixedCHAR(索引,javaTypeDescriptor.unwrap(值,String.class,选项));
}否则{
st.setString(索引,javaTypeDescriptor.unwrap(值,String.class,选项));
}
}否则{
st.setString(索引,javaTypeDescriptor.unwrap(值,String.class,选项));
}
}
@凌驾
受保护的void doBind(CallableStatement st、X值、字符串名称、包装器选项)
抛出SQLException{
//Hibernate在当前版本中不再使用
st.setString(名称,javaTypeDescriptor.unwrap(值,String.class,选项));
}
私有布尔checkIfCHARByName(ResultSetMetaData元数据,字符串名称)
抛出SQLException{

对于(int i=1;i)代码在哪里?抱歉,添加了一些代码和说明
  @Autowired
  private DataSource source;

  @Bean
  public HibernateJpaVendorAdapter getHibernateJPAVendorAdapter() {
    return new CustomHibernateJpaVendorAdaptor();
  }

  private static class CustomHibernateJpaVendorAdaptor extends HibernateJpaVendorAdapter {

    @Override
    protected Class<?> determineDatabaseDialectClass(Database database) {
      // if HSQL is copied from Spring Sourcecode to keep everything the same
      if (Database.HSQL.equals(database)) {
        return CustomHsqlDialect.class;
      }
      try {
        if (source.isWrapperFor(OracleDataSource.class)) {
          return CustomOracleDialect.class;
        }
      } catch (SQLException e) {
      }
      return super.determineDatabaseDialectClass(database);
    }

    private class CustomHsqlDialect extends HSQLDialect {

      public CustomHsqlDialect() {
        registerColumnType(Types.BOOLEAN, "boolean");
        registerHibernateType(Types.BOOLEAN, "boolean");
      }
    }
  }

  @NoArgsConstructor
  public static class CustomOracleDialect extends Oracle12cDialect {

    private static final OracleCharFix INSTANCE = new OracleCharFix();


    @Override
    protected SqlTypeDescriptor getSqlTypeDescriptorOverride(final int sqlCode) {
      switch (sqlCode) {
        case Types.VARCHAR:
          return INSTANCE;
        default:
          return super.getSqlTypeDescriptorOverride(sqlCode);
      }
    }
  }

  @Slf4j
  private static class OracleCharFix extends CharTypeDescriptor {

    @Override
    public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
      return new BasicBinder<>(javaTypeDescriptor, this) {
        @Override
        protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
          throws SQLException {
          if (st.isWrapperFor(OraclePreparedStatement.class)) {
            OraclePreparedStatement ops = st.unwrap(OraclePreparedStatement.class);
            if (ops.getParameterMetaData().getParameterType(index) == Types.CHAR) {
              ops.setFixedCHAR(index, javaTypeDescriptor.unwrap(value, String.class, options));
            } else {
              st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
            }
          } else {
            st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
          }
        }

        @Override
        protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
          throws SQLException {
            //Is nolonger used by Hibernate in the current Version
            st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
        }

        private boolean checkIfCHARByName(ResultSetMetaData metadata, String name)
          throws SQLException {
          for (int i = 1; i <= metadata.getColumnCount(); i++) {
            if (metadata.getColumnType(i) == Types.CHAR && Objects.equals(metadata.getColumnName(i), name)) {
              return true;
            }
          }
          return false;
        }
      };
    }