简体   繁体   English

如何将Hibernate从MySQL迁移到SQL Server?

[英]How to migrate Hibernate from MySQL to SQL Server?

I need to migrate my JPA/Hibernate (5.1) Java EE application from MySQL to SQL Server (2012). 我需要将我的JPA / Hibernate(5.1)Java EE应用程序从MySQL迁移到SQL Server(2012)。 Since the abstraction provided by JPA, my humble thought was about this being simple and straightforward. 自从JPA提供抽象以来,我的谦虚思想就是简单明了。

I started loading the SQL Server JDBC 4.2 drivers on Wildfly 10, downloaded from Microsoft website, and defining the new datasource resulting in a successful connection test. 我开始在Wildfly 10上加载SQL Server JDBC 4.2驱动程序,从Microsoft网站下载,并定义新的数据源,从而成功进行连接测试。

Then, I republished my application letting Hibernate reconstruct the database tables, but I'm stuck on this: 然后,我重新发布了我的应用程序让Hibernate重建数据库表,但我坚持这个:

13:27:29,268 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ServerService Thread Pool -- 61) SQL Error: 1038, SQLState: S0004
13:27:29,268 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ServerService Thread Pool -- 61) An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
13:27:29,270 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 61) MSC000001: Failed to start service jboss.persistenceunit."best.war#best": org.jboss.msc.service.StartException in service jboss.persistenceunit."best.war#best": javax.persistence.PersistenceException: [PersistenceUnit: best] Unable to build Hibernate SessionFactory
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:172)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:117)
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:182)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: best] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:884)
    at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:154)
    ... 7 more
Caused by: org.hibernate.exception.SQLGrammarException: Error accessing table metadata
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
    at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.convertSQLException(InformationExtractorJdbcDatabaseMetaDataImpl.java:99)
    at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.locateTableInNamespace(InformationExtractorJdbcDatabaseMetaDataImpl.java:354)
    at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.getTable(InformationExtractorJdbcDatabaseMetaDataImpl.java:228)
    at org.hibernate.tool.schema.internal.exec.ImprovedDatabaseInformationImpl.getTableInformation(ImprovedDatabaseInformationImpl.java:109)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.performMigration(SchemaMigratorImpl.java:252)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:137)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:110)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:176)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:458)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881)
    ... 9 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:217)
    at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onEOF(tdsparser.java:251)
    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:81)
    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:36)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:1834)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:6276)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1793)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(SQLServerConnection.java:1839)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.setCatalog(SQLServerConnection.java:2190)
    at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.switchCatalogs(SQLServerDatabaseMetaData.java:331)
    at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetFromStoredProc(SQLServerDatabaseMetaData.java:282)
    at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetWithProvidedColumnNames(SQLServerDatabaseMetaData.java:309)
    at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getTables(SQLServerDatabaseMetaData.java:496)
    at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.locateTableInNamespace(InformationExtractorJdbcDatabaseMetaDataImpl.java:339)
    ... 19 more

13:27:29,278 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "best.war")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"best.war#best\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"best.war#best\": javax.persistence.PersistenceException: [PersistenceUnit: best] Unable to build Hibernate SessionFactory
    Caused by: javax.persistence.PersistenceException: [PersistenceUnit: best] Unable to build Hibernate SessionFactory
    Caused by: org.hibernate.exception.SQLGrammarException: Error accessing table metadata
    Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as \"\" or [] are not allowed. Change the alias to a valid name."}}
13:27:29,300 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 34) WFLYSRV0010: Deployed "best.war" (runtime-name : "best.war")
13:27:29,301 INFO  [org.jboss.as.controller] (Controller Boot Thread) WFLYCTL0183: Service status report
WFLYCTL0186:   Services which failed to start:      service jboss.persistenceunit."best.war#best": org.jboss.msc.service.StartException in service jboss.persistenceunit."best.war#best": javax.persistence.PersistenceException: [PersistenceUnit: best] Unable to build Hibernate SessionFactory

What's happening? 发生了什么? This is my persistence.xml : 这是我的persistence.xml

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="best" transaction-type="JTA">
        <jta-data-source>java:/datasource/mssql/best</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="update" />
        </properties>
    </persistence-unit>
  </persistence-units>
</persistence>

I tried also adding this, since I'm on SQL Server 2012, but nothing changed: 我尝试添加这个,因为我在SQL Server 2012上,但没有改变:

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

Any idea or suggestion? 有什么想法或建议吗?

Update 更新

Issue seems to happen only with hibernate.hbm2ddl.auto = update , since with create it works. 问题似乎只发生在hibernate.hbm2ddl.auto = update ,因为create它有效。 But I really need update to work like it did with MySQL, since I'm on heavy development and my schema changes frequently. 但是我真的需要像MySQL那样update工作,因为我正在进行大量开发并且我的架构经常更改。

SQL Server requires explicit catalog and schema settings. SQL Server需要显式的目录架构设置。

additional description in persistence.xml: persistence.xml中的其他说明:

<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />
<property name="hibernate.default_catalog" value="[database name]" />
<property name="hibernate.default_schema" value="dbo" />
<property name="hibernate.id.new_generator_mappings" value="false" />

refs: 裁判:

The problem rises when you use @Table with a schema value but no catalog value and no hibernate.default_catalog is specified in persistence.xml. 当您使用带有架构值的@Table但没有目录值且在persistence.xml中未指定hibernate.default_catalog时,问题就会出现。

This is a bug in my pov. 这是我的pov中的一个错误。 It worked in 4.3 very well. 它在4.3中工作得非常好。 Now Hibernate does not issue the correct query to SQL Server if in @Table only schema is specified and no catalog! 现在,如果在@Table中只指定了架构且没有目录,Hibernate不会向SQL Server发出正确的查询! I raised a bug here: https://hibernate.atlassian.net/browse/HHH-10978 我在这里提出了一个错误: https//hibernate.atlassian.net/browse/HHH-10978

MySQL and SQL Server both have some specific keywords or reserved names. MySQL和SQL Server都有一些特定的关键字或保留名称。

Check that your entities don't use any as table name or column name. 检查您的实体是否不使用任何表名或列名。

I had a similar problem using hibernate 5.1.0.Final with SQL Server 2012. I downgraded to hibernate 4.3.11.Final and solved the problem. 我使用hibernate 5.1.0.Final与SQL Server 2012有类似的问题。我降级到休眠4.3.11.Final并解决了问题。

Hibernate EntityManager 5.1.0.Final Hibernate EntityManager 5.1.0.Final

INFO  Version:37 - HHH000412: Hibernate Core {5.1.0.Final}
INFO  Environment:213 - HHH000206: hibernate.properties not found
INFO  Environment:317 - HHH000021: Bytecode provider name : javassist
INFO  Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
INFO  Dialect:156 - HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
INFO  Version:30 - HV000001: Hibernate Validator 5.2.4.Final
WARN  SqlExceptionHelper:129 - SQL Error: 1038, SQLState: S0004
ERROR SqlExceptionHelper:131 - Falta o está vacío un nombre de objeto o columna. Compruebe si todas las columnas de las instrucciones SELECT INTO tienen un nombre. Para otras instrucciones, busque si hay nombres de alias vacíos. No se permiten los alias definidos como "" o []. Cambie el alias por un nombre válido.

Hibernate EntityManager 4.3.11.Final Hibernate EntityManager 4.3.11.Final

Version:54 - HHH000412: Hibernate Core {4.3.11.Final}
Environment:239 - HHH000206: hibernate.properties not found
Environment:346 - HHH000021: Bytecode provider name : javassist
Version:66 - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
Dialect:145 - HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
ASTQueryTranslatorFactory:47 - HHH000397: Using ASTQueryTranslatorFactory
Version:30 - HV000001: Hibernate Validator 5.2.4.Final
SchemaValidator:157 - HHH000229: Running schema validator
SchemaValidator:165 - HHH000102: Fetching database metadata
TableMetadata:65 - HHH000261: Table found: rino.rino.tipo_ticket

Hope this helps! 希望这可以帮助!

I am late to this thread here but landed here when I could not get Spring Boot JPA working with MS SQL Server the way it worked with MySQL and Postgres. 我迟到了这个帖子,但是当我无法让Spring Boot JPA与MySQL SQL和Postgres一起工作时使用MS SQL Server。

This thread has been very helpful with Spring Boot 1.5.9.RELEASE which uses Hibernate 5.0.12.Final . 这个线程对使用Hibernate 5.0.12.Final的 Spring Boot 1.5.9.RELEASE非常有帮助。

Also note that many tutorials show the Spring Boot application.propeties file with entries for the database and hibernate which have now been superseded with newer properties by Spring Boot. 另请注意,许多教程都显示了Spring Boot application.propeties文件,其中包含数据库和hibernate的条目,这些条目现在已被Spring Boot的新属性所取代。

So if you are using Spring Boot with Microsoft SQL Server, use the following style of properties 因此,如果您将Spring Boot与Microsoft SQL Server一起使用,请使用以下样式的属性

spring.datasource.url=jdbc:sqlserver://127.0.0.1:1433;jdbc.databaseName=mydb
spring.datasource.username=admin
spring.datasource.password=aadmin
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.database=sql-server
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

And in your entities you need to provide the following schema information: 在您的实体中,您需要提供以下架构信息:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(schema="dbo", name="MyUser",catalog="mydatabase")
public class MyUser {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String name;
    private int age;

    public MyUser() {
    }

    public MyUser(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" + ", name='" + name + '\'' + ", Age=" + age + '}';
    }
}

Note: The catalog attribue of the @Table annotation should be your database name. 注意: @Table注释的catalog属性应该是您的数据库名称。 It is required for connecting and accessing Microsoft SQL Server when using the combination of Spring Boot and Hibernate as mentioned above. 当使用如上所述的Spring Boot和Hibernate的组合时,它是连接和访问Microsoft SQL Server所必需的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM