前言
問題描述
在springboot項(xiàng)目中使用springdata Jpa芭届,并且希望當(dāng)我的實(shí)體類發(fā)生了更改图呢,數(shù)據(jù)庫表結(jié)構(gòu)隨著實(shí)體類的改變而自動做出相應(yīng)的改變挣输。故在application.properties文件中設(shè)置屬性spring.jpa.hibernate.ddl-auto=update侮叮。然而在啟動的時候報錯较解,報錯信息如下:
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:259)
at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onEOF(tdsparser.java:256)
at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:108)
at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:28)
at com.microsoft.sqlserver.jdbc.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:2754)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7344)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2713)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(SQLServerConnection.java:2759)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.setCatalog(SQLServerConnection.java:3076)
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.switchCatalogs(SQLServerDatabaseMetaData.java:345)
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetFromStoredProc(SQLServerDatabaseMetaData.java:297)
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetWithProvidedColumnNames(SQLServerDatabaseMetaData.java:321)
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getTables(SQLServerDatabaseMetaData.java:493)
at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.locateTableInNamespace(InformationExtractorJdbcDatabaseMetaDataImpl.java:339)
... 31 common frames omitted
技術(shù)棧
- springboot 1.5.6
- springdata jpa
- sqlServer2014
UserEntity實(shí)體類
@Entity
@Table(name = "user_entity", schema = "yueyue")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer uid;
@Column(name = "username", columnDefinition = "varchar(255)", nullable = false)
private String username;
@Column(name = "password", columnDefinition = "varchar(255)", nullable = false)
private String password;
}
application.yml
spring:
datasource:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://localhost;databaseName=testdb;sendStringParametersAsUnicode=false
username: sa
password: Abcd1234
jpa:
hibernate:
ddl-auto: update
dialect: org.hibernate.dialect.SQLServer2012Dialect
show-sql: true
解決思路
看拋出來的錯誤信息并不是很明顯知道錯誤在哪嚎花,我們還是debug進(jìn)代碼里面看具體做了什么操作寸痢,挑一個比較顯眼的方法打個斷點(diǎn)。這里我選擇at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetFromStoredProc(SQLServerDatabaseMetaData.java:297)
這個方法紊选,這個方法的意思是通過調(diào)用存儲過程得到結(jié)果集啼止,錯誤信息顯示的是在297行,再進(jìn)入switchCatalogs方法兵罢。這段代碼的邏輯很清晰献烦,拿到當(dāng)前數(shù)據(jù)庫的catalog(默認(rèn)是數(shù)據(jù)庫名),然后和傳進(jìn)來的catalog做對比卖词,如果相同返回null巩那,如果不同就將數(shù)據(jù)庫的catalog設(shè)置成傳進(jìn)來的值吏夯,最后返回該值。
在switchCatalogs方法中的第一行打上斷點(diǎn)即横,重新debug啟動springboot的引導(dǎo)類噪生,進(jìn)入到斷點(diǎn)里面,可以看到相應(yīng)的變量值东囚,我們傳進(jìn)來的catelog為空字符串跺嗽,所以執(zhí)行
connection.setCatalog("")
這句代碼,而數(shù)據(jù)庫的catalog是不允許為空的页藻,所以拋出SQLServerException桨嫁,就看到文章開頭的錯誤信息。
解決方案
當(dāng)一切邏輯都很清晰時份帐,自然bug改起來也是省時省力璃吧。只需要在相應(yīng)的實(shí)體類@Table注解上加上catalog屬性就行了,這里我改成數(shù)據(jù)庫名废境。最后重啟app畜挨。
修改后的UserEntity
@Entity
@Table(name = "user_entity", schema = "yueyue", catalog = "testdb")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer uid;
@Column(name = "username", columnDefinition = "varchar(255)", nullable = false)
private String username;
@Column(name = "password", columnDefinition = "varchar(255)", nullable = false)
private String password;
}
總結(jié)
最后一個小小的總結(jié)作為本文的結(jié)束,使用springdata jpa時彬坏,如果希望實(shí)體類發(fā)生更改而數(shù)據(jù)庫表做出相應(yīng)的更改且不破壞數(shù)據(jù)庫現(xiàn)有的數(shù)據(jù),要將spring.jpa.hibernate.ddl-auto屬性值設(shè)置為update膝晾,同時需要在實(shí)體類上的@Table注解中加上catalog屬性栓始,值為數(shù)據(jù)庫名。
這里其實(shí)還是有一些小小的不足血当,就算你設(shè)置成update值幻赚,它也并不能識別你對數(shù)據(jù)庫表結(jié)構(gòu)的所有更改,它往往只能識別出你增加的字段臊旭,比如修改字段名落恼,修改字段類型或者刪除一個字段它都是不能夠識別的。
總的來說离熏,只是使用這個屬性值來對數(shù)據(jù)庫做版本控制是有很大的局限性的佳谦。在實(shí)際開發(fā)中,我們更多會用到flyway這個工具滋戳,這里就不再做多闡述钻蔑。
thanks for reading,see u next time~~~
wangyue