在hibernate中直接執行原生sql遇到型別轉換問題
今天做了個用hibernate直接執行原生sql的查詢,遇到char型別的資料庫欄位查出來只能截斷成一位,後經高人指導,要用自定義的方言,如下:
public class OracleDialect extends Oracle10gDialect
{
public OracleDialect()
{
registerHibernateType(91, Hibernate.TIMESTAMP.getName());
registerHibernateType(1, Hibernate.STRING.getName());
}
}
然後又在在網上查了一下,裡面提到很高關於自定義方言來解決一些資料庫欄位型別的問題,這裡總結一下。方便大家查詢。
第一種: No Dialect mapping for JDBC type: 3;
檢視文章 |
今天在使用getSession().createSQLQuery("SELECT SUM(aloneIp) FROM table").list(); 時出現了錯誤:No Dialect mapping for JDBC type: 3; baidu,google了一番後,各位都說:“出現這個原因是說伺服器端的資料型別並不能和Java的BigDecimal資料型別成功對映。”; 不過我的資料庫中“aloneIp”列的型別為INTEGER,出現這個錯誤不知是何原因。 根據以下解決方法,問題得以解決,記錄之: 1、新建一個MMySQLDialect extends org.hibernate.dialect.MySQLDialect (我使用的資料庫是MYSQL)並在裡面補充註冊新的型別對映。如下: import java.sql.Types; import org.hibernate.Hibernate; import org.hibernate.dialect.MySQLDialect; public class MMySQLDialect extends MySQLDialect { public MMySQLDialect () { super(); registerHibernateType(Types.DECIMAL, Hibernate.BIG_INTEGER.getName()); } } 2、把Hibernate裡的Dialect改成我們第一步新建的新的Dialect |
第二種: org.hibernate.MappingException: No Dialect mapping for JDBC type: -1
環境是:SQL Server2005 + Hibernate3.2.5
問題原因:
資料庫表中有text型別的欄位,而Hibernate在native查詢中沒有註冊這個欄位,因此發生這個錯誤。
解決方法:
寫一個類、修改hibernate配置檔案。 寫一個Dialect的子類,這裡我 extends SQLServerDialectt類:
package com.zy.util;
import java.sql.Types;
import org.hibernate.Hibernate;
import org.hibernate.dialect.SQLServerDialect;
public class DialectForInkfish extends SQLServerDialect {
public DialectForInkfish() {
super();
//registerHibernateType(Types.LONGVARCHAR, 65535, "text");//.LONGVARCHAR
registerHibernateType(Types.DECIMAL, Hibernate.BIG_DECIMAL.getName());
registerHibernateType(-1, Hibernate.STRING.getName());
}
}
修改Hibernate配置檔案hibernate.cfg.xml,把
<property name="dialect">
org.hibernate.dialect.SQLServerDialect
</property>
修改成:
<property name="dialect">
com.zy.util.DialectForInkfish
</property>
說明: 如果你的資料庫是mysql,而又用了decimal型別,報錯應該是 No Dialect mapping for JDBC type: 3 . 注意這個3, 它說明hibernate不能將這種資料型別對映到你的java類中. 就需要在自定義的方言中用到:
registerHibernateType(Types.DECIMAL, Hibernate.BIG_DECIMAL.getName());
一個比較詳細的說明:
前段時間碰到了這類錯誤,最後的問號表示不確定的數字,但是解決的方法都一樣。
首先,自定義一個方言類——Hibernate Dialect,該類需要繼承與我們使用的資料庫相應的方言類。比如:如果我們用的是MySql(版本為5.x.x),我們需要繼承“org.hibernate.dialect.MySQL5Dialect”;如果我們使用的是DB2,那麼我們應該繼承“org.hibernate.dialect.DB2Dialect”;我用的是SqlServer2008,所以我要繼承“org.hibernate.dialect.SQLServerDialect”,參考程式碼如下:
Java程式碼- import java.sql.Types;
- import org.hibernate.Hibernate;
- import org.hibernate.dialect.SQLServerDialect;
- public class SqlServer2008Dialect extends SQLServerDialect {
- public SqlServer2008Dialect() {
- super();
- registerHibernateType(Types.CHAR, Hibernate.STRING.getName());
- registerHibernateType(Types.NVARCHAR, Hibernate.STRING.getName());
- registerHibernateType(Types.LONGNVARCHAR, Hibernate.STRING.getName());
- registerHibernateType(Types.DECIMAL, Hibernate.DOUBLE.getName());
- }
- }
import java.sql.Types;
import org.hibernate.Hibernate;
import org.hibernate.dialect.SQLServerDialect;
public class SqlServer2008Dialect extends SQLServerDialect {
public SqlServer2008Dialect() {
super();
registerHibernateType(Types.CHAR, Hibernate.STRING.getName());
registerHibernateType(Types.NVARCHAR, Hibernate.STRING.getName());
registerHibernateType(Types.LONGNVARCHAR, Hibernate.STRING.getName());
registerHibernateType(Types.DECIMAL, Hibernate.DOUBLE.getName());
}
}
總之大家可以在“org.hibernate.dialect”這個package中找到與資料庫相對應的方言類。在其中,我們需要注意三點點:
a、在預設構造方法中繼承父類構造方法,同時呼叫“registerHibernateType(int code, String name)”方法將資料庫中該資料型別對映到相應的java型別。code表示資料庫中的資料型別整數表示,可以在“java.sql.Types”類中查到相應的資料庫型別。name表示我們要對映的java型別。可以從“org.hibernate.Hibernate”中查到。
b、Types類。在Types中定義了資料庫常用的欄位型別,如:
Java程式碼- ……
- public final static int LONGVARCHAR = -1;
- public final static int TIMESTAMP = 93;
- ……
……
public final static int LONGVARCHAR = -1;
public final static int TIMESTAMP = 93;
……
我們可以根據“No Dialect mapping for JDBC type : ”後面緊跟的數字在該類(Types)中找到相應的型別。我們也可以根據資料表中欄位的型別找到相應的值。這個值就是registerHibernateType(int code, String name)的第一個引數。
c、Hibernate類。Hibernate中定義了轉換的目的型別,如第一段程式碼所示。能夠轉化成什麼型別,可以在該類中查詢。通過呼叫“getName()”方法得到一個String型。當然,如果你記住了,我們還可以這樣寫
Java程式碼- import org.hibernate.dialect.SQLServerDialect;
- public class SqlServer2008Dialect extends SQLServerDialect {
- public SqlServer2008Dialect() {
- super();
- registerHibernateType(1, "string");
- registerHibernateType(-9, "string");
- registerHibernateType(-16, "string");
- registerHibernateType(3, "double");
- }
- }
import org.hibernate.dialect.SQLServerDialect;
public class SqlServer2008Dialect extends SQLServerDialect {
public SqlServer2008Dialect() {
super();
registerHibernateType(1, "string");
registerHibernateType(-9, "string");
registerHibernateType(-16, "string");
registerHibernateType(3, "double");
}
}
其實和上面是一樣的,只是把上面所代表的值直接寫出來了。O(∩_∩)O哈哈~。需要注意的是super()方法的呼叫,不呼叫該方法是否會出現錯誤,我這就不知道了,這個我沒有做過測試,所以最好調一下。
然後,我們還需要在配置檔案中作修改。我用的是EJB3,所以我在META-INF資料夾下的persistent.xml檔案中新增屬性“hibernate.dialect”,value值為“xxx.xxx.SqlServer2008Dialect ”,xxx表示包名,這個大家都知道。程式碼如下:
Java程式碼- <?xml version="1.0" encoding="UTF-8" ?>
- <persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
- http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
- <persistence-unit name="DateSource">
- <jta-data-source>java:/SqlServerDS</jta-data-source>
- <properties>
- <property name="hibernate.dialect" value="xxx.xxx.SqlServer2008Dialect"/>
- <property name="hibernate.hbm2ddl.auto" value="none" />
- </properties>
- </persistence-unit>
- </persistence>
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="DateSource">
<jta-data-source>java:/SqlServerDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="xxx.xxx.SqlServer2008Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="none" />
</properties>
</persistence-unit>
</persistence>
打包部署,OK!當然,如果你使用的是Hibernate,則修改Hibernate配置檔案hibernate.cfg.xml,將“hibernate.dialect”屬性的值改為自己的方言類“xxx.xxx.SqlServer2008Dialect ”即可。