成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Spring Data JPA 自動生成表結(jié)構(gòu)

lewif / 3651人閱讀

摘要:想在部署的時候隨應(yīng)用的啟動而初始化數(shù)據(jù)腳本,這不就是中的自動生成表結(jié)構(gòu),聽起來特別簡單,不就是配置的嘛,有什么好說的,是個人都知道。

想在部署的時候隨應(yīng)用的啟動而初始化數(shù)據(jù)腳本,這不就是Spring Data Jpa中的自動生成表結(jié)構(gòu),聽起來特別簡單,不就是配置Hibernateddl-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以及@ApiModelPropertyswagger注解。

我們注冊賬號的單元測試就可以直接寫成下面這樣,僅填寫賬號和密碼,其他值則由數(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

相關(guān)文章

  • SpringBoot2.0之三 優(yōu)雅整合Spring Data JPA

    摘要:的配置后在其他低版本的中也有使用這種配置的,具體根據(jù)版本而定。等注解是的相關(guān)知識,后面的文章將詳細講述。 ??在我們的實際開發(fā)的過程中,無論多復(fù)雜的業(yè)務(wù)邏輯到達持久層都回歸到了增刪改查的基本操作,可能會存在關(guān)聯(lián)多張表的復(fù)雜sql,但是對于單表的增刪改查也是不可避免的,大多數(shù)開發(fā)人員對于這個簡單而繁瑣的操作都比較煩惱。 ??為了解決這種大量枯燥的簡單數(shù)據(jù)庫操作,大致的解決該問題的有三種方...

    ningwang 評論0 收藏0
  • 【從零入門系列-2】Spring Boot 之 數(shù)據(jù)庫實體定義實現(xiàn)

    摘要:文章系列從零入門系列之從零入門系列之程序結(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)...

    nemo 評論0 收藏0
  • Spring Boot快速入門(四):使用jpa進行數(shù)據(jù)庫操作

    摘要:最常用的屬性,第一次加載時根據(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加入...

    Kyxy 評論0 收藏0
  • 一起來學(xué)SpringBoot | 第六篇:整合SpringDataJpa

    摘要:忽略該字段的映射省略創(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...

    Dionysus_go 評論0 收藏0
  • Spring Boot 教程(二):使用Spring Boot JPA完成數(shù)據(jù)層訪問

    摘要:教程簡介本項目內(nèi)容為教程樣例。目的是通過學(xué)習(xí)本系列教程,讀者可以從到掌握的知識,并且可以運用到項目中。本章將進一步講解,結(jié)合完成數(shù)據(jù)層訪問。創(chuàng)建控制器在下面創(chuàng)建控制器用于測試訪問程序運行和調(diào)試在類中,啟動程序。 教程簡介 本項目內(nèi)容為Spring Boot教程樣例。目的是通過學(xué)習(xí)本系列教程,讀者可以從0到1掌握spring boot的知識,并且可以運用到項目中。如您覺得該項目對您有用,...

    DevWiki 評論0 收藏0

發(fā)表評論

0條評論

lewif

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<