摘要:想在部署的時候隨應(yīng)用的啟動而初始化數(shù)據(jù)腳本,這不就是中的自動生成表結(jié)構(gòu),聽起來特別簡單,不就是配置的嘛,有什么好說的,是個人都知道。
想在部署的時候隨應(yīng)用的啟動而初始化數(shù)據(jù)腳本,這不就是Spring Data Jpa中的自動生成表結(jié)構(gòu),聽起來特別簡單,不就是配置Hibernate的ddl-auto嘛,有什么好說的,是個人都知道。當(dāng)初我也是這樣認為,實際操作了一把,雖然表是創(chuàng)建成功了,但是字段注釋,字符集以及數(shù)據(jù)庫引擎都不對,沒想到在這些細節(jié)上翻車了。
畢竟開翻的車還要自己扶起來,粗略寫點救援過程。
注:本文中使用的Spring Data JPA版本為2.1.4.RELEASE
以MySQL為例,其它數(shù)據(jù)庫可自行驗證:
import com.fasterxml.jackson.annotation.*; import org.hibernate.annotations.*; import org.springframework.data.annotation.*; import javax.persistence.*; import javax.persistence.Entity; import javax.persistence.Id; import java.math.BigDecimal; @Entity @javax.persistence.Table(name = "basic_city") @org.hibernate.annotations.Table(appliesTo = "basic_city", comment = "城市基本信息") public class CityDO { @Id @GenericGenerator(name = "idGenerator", strategy = "uuid") @GeneratedValue(generator = "idGenerator") @Column(name = "CITY_ID", length = 32) private String cityId; @Column(name = "CITY_NAME_CN", columnDefinition = "VARCHAR(255) NOT NULL COMMENT "名稱(中文)"") private String cityNameCN; @Column(name = "CITY_NAME_EN", columnDefinition = "VARCHAR(255) NOT NULL COMMENT "名稱(英文)"") private String cityNameEN; @Column(name = "LONGITUDE", precision = 10, scale = 7) private BigDecimal longitude; @Column(name = "LATITUDE", precision = 10, scale = 7) private BigDecimal latitude; @Column(name = "ELEVATION", precision = 5) private Integer elevation; @Column(name = "CITY_DESCRIPTION", length = 500) private String cityDescription; // 構(gòu)造方法及get/set方法省略 }
用到的注解簡要說明一下:
@javax.persistence.Table 修改默認ORM規(guī)則,屬性name設(shè)置表名;
@org.hibernate.annotations.Table 建表時的描述, 屬性comment修改表描述;
@Id 主鍵
@GenericGenerator 該注解為Hibernate的注解,用來生成表的主鍵策略,屬性strategy的值在類DefaultIdentifierGeneratorFactory中定義:
uuid2: UUIDGenerator.class;
guid: GUIDGenerator.class;
uuid: UUIDHexGenerator.class;
uuid.hex: UUIDHexGenerator.class;
assigned: Assigned.class;
identity: IdentityGenerator.class;
select: SelectGenerator.class;
sequence: SequenceStyleGenerator.class;
seqhilo: SequenceHiLoGenerator.class;
increment: IncrementGenerator.class;
foreign: ForeignGenerator.class;
sequence-identity: SequenceIdentityGenerator.class;
enhanced-sequence: SequenceStyleGenerator.class;
enhanced-table: TableGenerator.class;
@GeneratedValue 設(shè)置主鍵策略,這里屬性generator指向@GenericGenerator策略的name,屬性strategy有四個枚舉值:
GenerationType.TABLE 使用一個額外的表來存儲主鍵;
GenerationType.SEQUENCE 使用序列的方式存儲,且需要數(shù)據(jù)庫底層支持;
GenerationType.IDENTITY 由數(shù)據(jù)庫生成,一般為主鍵自增等;
GenerationType.AUTO 表示由程序生成,不聲明則默認為該屬性;
@Column 修改默認的ORM規(guī)則,屬性有:
name設(shè)置表中字段名稱,表字段和實體類屬性相同,則該屬性可不寫;
unique設(shè)置該字段在表中是否唯一,默認false;
nullable是否可為空,默認true;
insertable表示insert操作時該字段是否響應(yīng)寫入,默認為true;
updatable表示update操作時該字段是否響應(yīng)修改,默認為true;
columnDefinition是自定義字段,可以用這個屬性來設(shè)置字段的注釋;
table表示當(dāng)映射多個表時,指定表的表中的字段,默認值為主表的表名;
length是長度,僅對varchar類型的字段生效,默認長度為255;
precision表示一共多少位;
scale表示小數(shù)部分占precision總位數(shù)的多少位,例子中兩者共同使用來確保經(jīng)緯度的精度;
接下來需要設(shè)置數(shù)據(jù)引擎和字符集,網(wǎng)上的例子都大把的繼承MySQL5InnoDBDialect,但是這個類已經(jīng)過期了,我們這里用MySQL5Dialect:
package com.jason.config; import org.hibernate.dialect.MySQL5Dialect; import org.springframework.stereotype.Component; @Component public class MySQL5TableType extends MySQL5Dialect { @Override public String getTableTypeString() { return "ENGINE=InnoDB DEFAULT CHARSET=utf8"; } }
然后在Spring Boot的配置文件中應(yīng)用上面定義的MySQL5TableType,使用spring.jpa.properties.hibernate.dialect配置(注意書寫格式,這里使用的是yml文件):
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/techno?useUnicode=true&characterEncoding=utf8 username: root password: root jpa: hibernate: ddl-auto: update database-platform: org.hibernate.dialect.MySQL5InnoDBDialect properties: hibernate: dialect: com.jason.config.MySQL5TableType
jpa.hibernate.ddl-auto使用update,其它值及說明為:
create: 啟動服務(wù)時都會重新創(chuàng)建表,且不管表存不存在;
create-drop: 啟動服務(wù)時都會重新創(chuàng)建表,且不管表存不存在,服務(wù)停止時刪除所有表,不管表中是否有數(shù)據(jù);
update: 啟動服務(wù)時,自動更新表結(jié)構(gòu),但數(shù)據(jù)庫表中存在的舊字段不會刪除;
validate: 啟動服務(wù)時驗證表結(jié)構(gòu),若表結(jié)構(gòu)存在差異則拋出異常;
至此,Sprign Data JPA生成表結(jié)構(gòu)就完成了,當(dāng)我們建立數(shù)據(jù)庫后,啟動服務(wù)就可以在MySQL中得到表結(jié)構(gòu)了,應(yīng)用可以通過ApplicaitonRunner或者CommandLineRunner接口一鍵部署,省去了初始化SQL等不必要的操作,這兩個接口的簡單使用可以參考我的另外一篇文章。
最后我們再上一個例子,主要是寫入默認值等,部分說明就直接以注釋的形式寫到代碼里,還有@ColumnDefault注解這里就不做說明,大家可以自己了解下:
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import org.hibernate.annotations.*; import org.springframework.data.jpa.repository.*; import javax.persistence.*; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.Temporal; import java.util.Date; @ApiModel(value = "賬號基礎(chǔ)信息") @Entity @Table(name = "basic_account") @org.hibernate.annotations.Table(appliesTo = "basic_account", comment = "賬號基礎(chǔ)信息表") public class AccountDO { @ApiModelProperty(name = "accountId", value = "賬號Id", hidden = true) @Id @GenericGenerator(name = "idGenerator", strategy = "uuid") @GeneratedValue(generator = "idGenerator") @Column(name = "ACCOUNT_ID", length = 32) private String accountId; @ApiModelProperty(name = "username", value = "賬號", dataType = "String", required = true) @Column(length = 32, nullable = false) private String username; // 假設(shè)密碼加密后長度為128 @ApiModelProperty(name = "password", value = "密碼", dataType = "String", required = true) @Column(length = 128, nullable = false) private String password; // 新建的賬號未過期,默認值給1,這個值由數(shù)據(jù)庫生成,則設(shè)置insertable為false @ApiModelProperty(name = "isAccountNonExpired", value = "賬號是否過期", hidden = true) @Column(name = "IS_ACCOUNT_EXPIRED", insertable = false, columnDefinition = "CHAR(1) NOT NULL DEFAULT "1" COMMENT "賬號 0:過期;1:未過期"") private Integer isAccountNonExpired; // 新建的賬號未鎖定,默認值給1,這個值由數(shù)據(jù)庫生成,則設(shè)置insertable為false @Column(name = "IS_ACCOUNT_LOCKED", insertable = false, columnDefinition = "CHAR(1) NOT NULL DEFAULT "1" COMMENT "賬號 0:鎖定;1:未鎖定"") @ApiModelProperty(name = "isAccountNonLocked", value = "賬號是否鎖定", hidden = true) private Integer isAccountNonLocked; // 新建的賬號密碼未過期,默認值給1,這個值由數(shù)據(jù)庫生成,則設(shè)置insertable為false @Column(name = "IS_CREDENTIALS_EXPIRED", insertable = false, columnDefinition = "CHAR(1) NOT NULL DEFAULT "1" COMMENT "密碼 0:已過期;1:未過期"") @ApiModelProperty(name = "isCredentialsNonExpired", value = "密碼是否過期", hidden = true) private Integer isCredentialsNonExpired; // 新建的賬號需要激活,默認值給0,這個值由數(shù)據(jù)庫生成,設(shè)置insertable為false @ApiModelProperty(name = "isEnabled", value = "賬號是否可用", hidden = true) @Column(name = "IS_ENABLE", insertable = false, columnDefinition = "CHAR(1) NOT NULL DEFAULT "0" COMMENT "賬號 0:不可用;1:可用"") private Integer isEnabled; // 新建的賬號,默認值給1,這個值由數(shù)據(jù)庫生成,設(shè)置insertable為false @ApiModelProperty(name = "isDelete", value = "賬號是否刪除", hidden = true) @Column(name = "IS_DELETE", insertable = false, columnDefinition = "CHAR(1) NOT NULL DEFAULT "1" COMMENT "賬號 0:已刪除;1:未刪除"") private Integer isDelete; // 新建賬號時間不能修改,設(shè)置updatable為false,但此處不能設(shè)置insertable = false // @Temporal(TemporalType.TIMESTAMP) 由于表字段類型為TIMESTAMP,所以將Date轉(zhuǎn)換為TIMESTAMP @ApiModelProperty(name = "createTimestamp", value = "創(chuàng)建時間") @Column(name = "CREATE_TIMESTAMP", nullable = false, updatable = false) @Temporal(TemporalType.TIMESTAMP) @CreationTimestamp private Date createTimestamp; public AccountDO(String username,String password) { this.username = username; this.password = password; } // 其他構(gòu)造方法及get/set方法省略 }
注:@ApiModel以及@ApiModelProperty為swagger注解。
我們注冊賬號的單元測試就可以直接寫成下面這樣,僅填寫賬號和密碼,其他值則由數(shù)據(jù)庫生成:
@Test public void saveAccount() throws Exception { accountService.saveAccount(new AccountDO("123456", "654321")); }
原創(chuàng)不易,感謝支持。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74340.html
摘要:的配置后在其他低版本的中也有使用這種配置的,具體根據(jù)版本而定。等注解是的相關(guān)知識,后面的文章將詳細講述。 ??在我們的實際開發(fā)的過程中,無論多復(fù)雜的業(yè)務(wù)邏輯到達持久層都回歸到了增刪改查的基本操作,可能會存在關(guān)聯(lián)多張表的復(fù)雜sql,但是對于單表的增刪改查也是不可避免的,大多數(shù)開發(fā)人員對于這個簡單而繁瑣的操作都比較煩惱。 ??為了解決這種大量枯燥的簡單數(shù)據(jù)庫操作,大致的解決該問題的有三種方...
摘要:文章系列從零入門系列之從零入門系列之程序結(jié)構(gòu)設(shè)計說明前言本篇文章開始代碼實踐,系統(tǒng)設(shè)計從底向上展開,因此本篇先介紹如何實現(xiàn)數(shù)據(jù)庫表實體類的設(shè)計實現(xiàn)。主鍵由數(shù)據(jù)庫自動生成主要是自動增長型主鍵由程序控制。 文章系列 【從零入門系列-0】Sprint Boot 之 Hello World 【從零入門系列-1】Sprint Boot 之 程序結(jié)構(gòu)設(shè)計說明 前言 本篇文章開始代碼實踐,系統(tǒng)...
摘要:最常用的屬性,第一次加載時根據(jù)類會自動建立起表的結(jié)構(gòu)前提是先建立好數(shù)據(jù)庫,以后加載時根據(jù)類自動更新表結(jié)構(gòu),即使表結(jié)構(gòu)改變了但表中的行仍然存在不會刪除以前的行。 添加依賴 新建項目選擇web,JPA,MySQL三個依賴 showImg(https://segmentfault.com/img/bV2gNo?w=1684&h=1172); 對于已存在的項目可以在bulid.gradle加入...
摘要:忽略該字段的映射省略創(chuàng)建數(shù)據(jù)訪問層接口,需要繼承,第一個泛型參數(shù)是實體對象的名稱,第二個是主鍵類型。 SpringBoot 是為了簡化 Spring 應(yīng)用的創(chuàng)建、運行、調(diào)試、部署等一系列問題而誕生的產(chǎn)物,自動裝配的特性讓我們可以更好的關(guān)注業(yè)務(wù)本身而不是外部的XML配置,我們只需遵循規(guī)范,引入相關(guān)的依賴就可以輕易的搭建出一個 WEB 工程 上一篇介紹了Spring JdbcTempl...
摘要:教程簡介本項目內(nèi)容為教程樣例。目的是通過學(xué)習(xí)本系列教程,讀者可以從到掌握的知識,并且可以運用到項目中。本章將進一步講解,結(jié)合完成數(shù)據(jù)層訪問。創(chuàng)建控制器在下面創(chuàng)建控制器用于測試訪問程序運行和調(diào)試在類中,啟動程序。 教程簡介 本項目內(nèi)容為Spring Boot教程樣例。目的是通過學(xué)習(xí)本系列教程,讀者可以從0到1掌握spring boot的知識,并且可以運用到項目中。如您覺得該項目對您有用,...
閱讀 1500·2021-11-22 15:11
閱讀 2905·2019-08-30 14:16
閱讀 2818·2019-08-29 15:21
閱讀 2961·2019-08-29 15:11
閱讀 2520·2019-08-29 13:19
閱讀 3044·2019-08-29 12:25
閱讀 478·2019-08-29 12:21
閱讀 2904·2019-08-29 11:03