No Dialect mapping for JDBC type -9
项目使用SSHM框架,使用Oracle数据库,编写了测试类测试报:No Dialect mapping for JDBC type-9,从错误可以看出是没有方言映射到JDBC的类型,由于使用的是Hibernate映射的数据库方言,且查询数据库字段是NVARCHAR2()类型的,这样问题就比较清晰了,是NVARCHAR2()类型映射不到Java数据类型,我的Hibernate配置如下:
<!-- Hibernate 配置 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${db.Dialect.prefix}.${db.Dialect.suffix}
</prop>
<prop key="hibernate.query.substitutions">
true '1', false '0'
</prop>
<prop key="hibernate.validator.apply_to_ddl">false</prop>
<prop key="hibernate.validator.autoregister_listeners">false</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
<prop key="hibernate.current_session_context_class">
org.springframework.orm.hibernate4.SpringSessionContext
</prop>
<prop key="jdbc.use_scrollable_resultset">false</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">
classpath*:/ehcache-hibernate.xml
</prop>
</props>
</property>
<property name="mappingJarLocations">
<list>
<value>/WEB-INF/lib/gene4.0.11120.jar</value>
<value>/WEB-INF/lib/module4.0.jar</value-->
</list>
</property>
<property name="packagesToScan">
<list>
<value>com.test.**.entity</value>
</list>
</property>
</bean>
Hibernate使用的方言是jdbc.properties中配置的,jdbc.properties配置的方言如下:
#=========================================
# DataBase Connection Setting Oracle
#=========================================
db.Dialect.prefix=org.hibernate.dialect
db.Dialect.suffix=OracleDialect
db.driverClassName=oracle.jdbc.driver.OracleDriver
db.url = jdbc:oracle:thin:@192.168.1.100:1521:orcl
db.username = test
db.password = test
配置中使用的方言是org.hibernate.dialect. OracleDialect,我们看看OracleDialect的源码:
/* */ package org.hibernate.dialect;
/* */
/* */ import org.hibernate.internal.CoreMessageLogger;
/* */ import org.hibernate.sql.CaseFragment;
/* */ import org.hibernate.sql.DecodeCaseFragment;
/* */ import org.hibernate.sql.JoinFragment;
/* */ import org.hibernate.sql.OracleJoinFragment;
/* */ import org.jboss.logging.Logger;
/* */
/* */ @Deprecated
/* */ public class OracleDialect
/* */ extends Oracle9Dialect
/* */ {
/* 45 */ private static final CoreMessageLogger LOG = (CoreMessageLogger)Logger.getMessageLogger(CoreMessageLogger.class, OracleDialect.class.getName());
/* */
/* */ public OracleDialect()
/* */ {
/* 55 */ LOG.deprecatedOracleDialect();
/* */
/* 58 */ registerColumnType(93, "date");
/* 59 */ registerColumnType(1, "char(1)");
/* 60 */ registerColumnType(12, 4000L, "varchar2($l)");
/* */ }
/* */
/* */ public JoinFragment createOuterJoinFragment()
/* */ {
/* 65 */ return new OracleJoinFragment();
/* */ }
/* */
/* */ public CaseFragment createCaseFragment()
/* */ {
/* 70 */ return new DecodeCaseFragment();
/* */ }
/* */
/* */ public String getLimitString(String sql, boolean hasOffset)
/* */ {
/* 76 */ sql = sql.trim();
/* 77 */ boolean isForUpdate = false;
/* 78 */ if (sql.toLowerCase().endsWith(" for update")) {
/* 79 */ sql = sql.substring(0, sql.length() - 11);
/* 80 */ isForUpdate = true;
/* */ }
/* */
/* 83 */ StringBuilder pagingSelect = new StringBuilder(sql.length() + 100);
/* 84 */ if (hasOffset) {
/* 85 */ pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
/* */ }
/* */ else {
/* 88 */ pagingSelect.append("select * from ( ");
/* */ }
/* 90 */ pagingSelect.append(sql);
/* 91 */ if (hasOffset) {
/* 92 */ pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
/* */ }
/* */ else {
/* 95 */ pagingSelect.append(" ) where rownum <= ?");
/* */ }
/* */
/* 98 */ if (isForUpdate) {
/* 99 */ pagingSelect.append(" for update");
/* */ }
/* */
/* 102 */ return pagingSelect.toString();
/* */ }
/* */
/* */ public String getSelectClauseNullString(int sqlType)
/* */ {
/* 107 */ switch (sqlType) {
/* */ case 1:
/* */ case 12:
/* 110 */ return "to_char(null)";
/* */ case 91:
/* */ case 92:
/* */ case 93:
/* 114 */ return "to_date(null)";
/* */ }
/* 116 */ return "to_number(null)";
/* */ }
/* */
/* */ public String getCurrentTimestampSelectString()
/* */ {
/* 122 */ return "select sysdate from dual";
/* */ }
/* */
/* */ public String getCurrentTimestampSQLFunctionName()
/* */ {
/* 127 */ return "sysdate";
/* */ }
/* */ }
/* Location: D:\Workspaces\MyEclipse Professional 2014\customerchat\WebRoot\WEB-INF\lib\hibernate-core-4.3.5.Final.jar
* Qualified Name: org.hibernate.dialect.OracleDialect
* Java Class Version: 6 (50.0)
* JD-Core Version: 0.7.0.1
*/
可以看出,OracleDialect继承的还是Oracle9的方言的类,版本太老了,没有对NVARCHAR2()类型的处理,比较两个版本的数据类型还是有不少差异的,再观察hibernate-core-4.3.5.Final.jar包可以发现,实现的最新版本是Oracle10gDialect,且并未对数据类型处理做什么改变,因此我们只有自己动手,实现方言类,让Hibernate使用我们自定义的类了,观察Oracle10gDialect,我们可以继承这个来,在构造函数中对数据类型进行处理:
import java.sql.Types;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.type.StandardBasicTypes;
public class MyOracleDialect extends Oracle10gDialect
{
public MyOracleDialect(){
registerHibernateType(Types.CHAR, StandardBasicTypes.STRING.getName());
registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName());
registerHibernateType(Types.LONGNVARCHAR, StandardBasicTypes.STRING.getName());
registerHibernateType(Types.DECIMAL, StandardBasicTypes.DOUBLE.getName());
registerHibernateType(Types.NCLOB, StandardBasicTypes.STRING.getName());
}
}
然后在修改jdbc.properties,使用我们自定义的类路径:
#=========================================
# DataBase Connection Setting Oracle
#=========================================
#db.Dialect.prefix=org.hibernate.dialect
#db.Dialect.suffix=OracleDialect
db.Dialect.prefix=com.test.utils
db.Dialect.suffix=MyOracleDialect
db.driverClassName=oracle.jdbc.driver.OracleDriver
db.url = jdbc:oracle:thin:@192.168.1.222:1521:orcl
db.username = test
db.password = test
然后重启服务器执行测试代码成功。
这里在提一点测试时使用的是junit,我们知道junit是通过指定applicationContext.xml来让容器加载我们创建的类的,由于我使用的是Hibernate的session,所以报了下面的错误:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
从错误中也可以看出是Hibernate获取session失败,而我使用服务器页面调代码测试就是成功的,查了半天原因就在于junit是直接加载applicationContext.xml来加载其他类的,而漏掉了web.xml中配置的Hibernate打开session的过滤器。。。
<filter>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这也是如果使用junit测试,且用到了Hibernate中的session时需要注意的地方。
上一篇: @Validated & @Valid 注解的区别
下一篇: 求各位数之和