用于MSSQL 2014的错误的hibernate方言

时间:2015-11-04 11:51:06

标签: java hibernate wildfly

我将使用序列的实体插入MSSQL 2014数据库时遇到问题。我使用Wildfly 10 CR4附带的hibernate(但在CR1和CR2中我遇到了同样的问题)。

以下是有关webapp运行环境的一般信息:

  1. Wildfly 10(CR4)
  2. Java 8 u 51
  3. Windows 7 Proffesional 64bit
  4. MSSQL Server 2014
  5. MSSQL驱动程序:sqljdbc42.jar部署在应用程序服务器上
  6. 我的persistence.xml文件如下所示:

    <persistence-unit name="mb_managed_pu" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:/jdbc/datasource</jta-data-source>
        <properties>
            <property name="hibernate.archive.autodetection" value="class, hbm" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.jdbc.batch_size" value="0" />
            <property name="hibernate.default_schema_" value="openmap"/>
            <property name="hibernate.connection.useUnicode" value="yes"/>
            <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
        </properties>
    </persistence-unit>
    

    现在我遇到错误时会发生什么。

    首先,当Wildfly启动时,我可以看到这个警告:

    WARN [org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver](ServerService线程池 - 68)HHH000385:使用SQL Server 2000方言的未知Microsoft SQL Server主要版本[12]

    我浏览了网页,发现这个问题自2015年1月以来就已为人所知,但不幸的是它仍然是an open issue

    当我尝试持久化具有配置为使用序列的ID的新实体时,会引发错误本身:

    @Id
    @Column(name = "MAP_BOOKMARK_ID")
    @SequenceGenerator(name = "SEQ_MAP_BOOKMARKS", sequenceName = "SEQ_MAP_BOOKMARKS", allocationSize = 1)
    @GeneratedValue(generator = "SEQ_MAP_BOOKMARKS", strategy = GenerationType.SEQUENCE)
    private long                    id;
    

    引发的例外情况如下:

    com.microsoft.sqlserver.jdbc.SQLServerException:无效的对象名称“SEQ_MAP_BOOKMARKS”。

    这并不奇怪,因为hibernate正在使用错误的方言 - 一个对序列一无所知的方言。

    当我修改persistence.xml并添加以下行时:

    <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect"/>
    

    一切都像魅力一样。

    问题是该应用程序还可以在另一台服务器上使用Oracle数据库,在另一台服务器上使用Postgres。我想避免为同一个应用程序准备多个版本。

    有人知道这个问题的解决方案吗?或者我应该等待另一个Wildfly和/或休眠版本出现?

4 个答案:

答案 0 :(得分:5)

同时团队没有解决这个问题,你可以创建一个自定义方言解析器:

public class ScopeStandardDialectResolver implements DialectResolver {


private static final long serialVersionUID = 1L;

    @Override
    public Dialect resolveDialect(DialectResolutionInfo info) {
        Dialect customDialectResolver = customDialectResolver(info);
        Log.getInstance().logInfo(Thread.currentThread().getStackTrace(), customDialectResolver.getClass().getName());
        return customDialectResolver;
    }

    private Dialect customDialectResolver(DialectResolutionInfo info) {
        final String databaseName = info.getDatabaseName();
        final int majorVersion = info.getDatabaseMajorVersion();
        if (isSqlServer2014(databaseName, majorVersion)) {
            return new SQLServer2012Dialect(); 
        } else {
            return StandardDialectResolver.INSTANCE.resolveDialect(info);
        }
    }

    private boolean isSqlServer2014(final String databaseName, final int majorVersion) {
        return databaseName.startsWith("Microsoft SQL Server") && majorVersion == 12;
    }

}

然后在持久性单元中进行配置:

<property name="hibernate.dialect_resolvers" value="com.oki.scope.hibernate.ScopeStandardDialectResolver" />

基于此示例:http://blog.exxeta.com/2016/03/23/dynamically-resolve-hibernate-database-dialect/

答案 1 :(得分:2)

我认为您的问题可能与此已知问题HHH-9570有关。 (该链接实际上包含我对我提议的解决方法的拉取请求)

基本上,就像之前的SQL Server 2012一样,Hibernate的StandardDialectResolver无法识别SQL Server 2014([主要版本12]),然后返回默认方言SQLServerDialect,这是SQL的一个Server 2000

答案 2 :(得分:2)

对于Springboot 1.4.7及更低版本,请在下面添加属性文件

spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.SQLServer2012Dialect

答案 3 :(得分:-5)

实际上这个问题是由于表格的映射不正确造成的。检查表和实体类映射。