2016-02-26 90 views
4

我需要遷移我的JPA /休眠(5.1)從MySQL的Java EE應用程序到SQL Server(2012)。由於JPA提供的抽象,我謙卑的想法是這個簡單而直接。如何將Hibernate從MySQL遷移到SQL Server?

我開始裝上Wildfly 10的SQL服務器JDBC驅動程序4.2,從微軟網站下載,並確定導致成功的連接測試新的數據源。

然後,我再版我的應用程序,讓休眠重建數據庫表,但我卡在此:

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 

發生了什麼事?這是我的persistence.xml

我也嘗試添加此,因爲我的SQL Server 2012上,但什麼都沒有改變:

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

任何想法或建議?

更新

問題似乎只與hibernate.hbm2ddl.auto = update發生,因爲有create它的工作原理。但我真的需要update工作像它與MySQL一樣,因爲我是沉重的發展和我的架構變化頻繁。

回答

4

SQL Server需要明確的目錄架構設置。

在持久性附加描述。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" /> 

裁判:

+0

hibernate.default_catalog = [數據庫名稱]修復它,謝謝! – BrunoJCM

+1

這是我的pov中的一個錯誤。它在4.3中工作得很好。現在,Hibernate不會向SQL Server發出正確的查詢,如果在@Table中只指定模式並且沒有目錄!我提出了一個錯誤https://hibernate.atlassian.net/browse/HHH-10978 –

0

MySQL和SQL Server都具有一些特定的關鍵字或保留的名稱。

檢查你的實體不使用任何作爲表名或列名。

+0

他們沒有,這都是JPA的默認設置。我沒有'@ Table'和'@ Column's,但是我發現這個問題只有'update' DDL,'create'有效。 –

+0

您是否嘗試切換到再次更新?您在上面寫道,只有在出現問題後才設置方言,可能會引入某種不可恢復的架構不匹配。 – newohybat

0

我不得不使用Hibernate 5.1.0.Final與SQL Server 2012類似的問題我降級冬眠4.3.11.Final和解決的問題。

休眠的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. 

休眠的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 

希望這有助於!

1

問題上升當您使用@Table與模式值,但沒有產品目錄值和無休眠.default_catalog在persistence.xml中指定。

這是我的pov中的一個bug。它在4.3中工作得很好。現在,Hibernate不會向SQL Server發出正確的查詢,如果在@Table中只指定模式並且沒有目錄!我在這裏提出了一個錯誤:https://hibernate.atlassian.net/browse/HHH-10978

0

我遲到了這裏的線程,但是在我無法獲得Spring Boot時JPA與MS SQL Server一起使用它與MySQL和Postgres一起工作的方式。

該線程已經非常有幫助和Spring引導1.5.9.RELEASE它使用Hibernate 5.0.12.Final

另請注意,許多教程顯示了Spring Boot application.propeties文件,其中包含數據庫和hibernate的條目,這些條目現在已被Spring Boot的新屬性取代。

所以,如果你使用Spring啓動與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 

,並在你的實體下面的風格,您需要提供以下架構信息:

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 + '}'; 
    } 
} 

注:@Table註釋的catalog屬性應該是您的數據庫名稱。如上所述,當使用Spring Boot和Hibernate的組合時,需要連接和訪問Microsoft SQL Server。