日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

jpa onetoone_拥抱开源从表设计到 JPA 实现

發(fā)布時(shí)間:2024/9/27 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jpa onetoone_拥抱开源从表设计到 JPA 实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

long?may?the?sunshine.

今天的我拿起鍵盤(pán)就是猛敲代碼。

果然,十分鐘后各種 JPA 報(bào)錯(cuò)開(kāi)始了。跟新手黨一樣,看到一個(gè)錯(cuò)誤就解決一個(gè),沒(méi)有好好思考為什么會(huì)出現(xiàn)這樣的錯(cuò)誤。

于是乎,遇到一個(gè)解決一個(gè),解決一個(gè)又遇到一個(gè),經(jīng)過(guò)數(shù)十個(gè)報(bào)錯(cuò)的來(lái)回起伏。

敏銳的我發(fā)現(xiàn)苗頭有些不對(duì)。全靠腦細(xì)胞的記憶,以及開(kāi)始對(duì)第一個(gè)錯(cuò)誤的解決過(guò)程開(kāi)始模糊不清了。

最后,我采用了《數(shù)據(jù)庫(kù) ER 圖》的方式,重新開(kāi)始分析、梳理。

也就是本文的初衷。

當(dāng)我寫(xiě)到最后的時(shí)候。我的 Junit 用例全部跑通了。贊。

以下是正文,稍微有點(diǎn)。。。。。。。。。。。。。長(zhǎng)。


01 數(shù)據(jù)庫(kù)?ER 圖

ER 圖概念

  • 實(shí)體 entity:用矩形表示,數(shù)據(jù)模型中的數(shù)據(jù)對(duì)象。

  • 屬性 attribute:用橢圓形表示,數(shù)據(jù)對(duì)象所具有的屬性(所具有的列)。其中唯一屬性 unique attribute,用下劃線表示。

  • 關(guān)系 relationshop:用菱形表示,數(shù)據(jù)對(duì)象與數(shù)據(jù)對(duì)象之間的聯(lián)系。

  • 假設(shè)有兩個(gè)實(shí)體集 A、B,它們有以下三種關(guān)聯(lián)關(guān)系。

  • 一對(duì)一 1:1

  • A 的每個(gè)實(shí)體至多與 B 的一個(gè)實(shí)體有關(guān)系。

  • B 的每個(gè)實(shí)體至多與 A 的一個(gè)實(shí)體有關(guān)系。

  • 滿足以上兩點(diǎn),即 A 與 B 的關(guān)系是一對(duì)一。

  • 一對(duì)多?1:N

  • A 的每個(gè)實(shí)體至少與 B 的 N(N>0)個(gè)實(shí)體有關(guān)系。

  • B 的每個(gè)實(shí)體至多與 A 的一個(gè)實(shí)體有關(guān)系。

  • 滿足以上兩點(diǎn),即 A 與 B 的關(guān)系是一對(duì)多,B 與 A 的關(guān)系是多對(duì)一。

  • 多對(duì)多?M:N

  • A 的每個(gè)實(shí)體至少與 B 的 M(M>0)個(gè)實(shí)體有關(guān)系。

  • B 的每個(gè)實(shí)體至少與 A 的 N(N>0)個(gè)實(shí)體有關(guān)系。

  • 滿足以上兩點(diǎn),即 A 與 B 的關(guān)系是多對(duì)多。


  • 02 JPA 關(guān)聯(lián)

    在 JPA 中分別使用 @OneToOne、@OneToMany、@ManyToOne、@ManyToMany 注解表示一對(duì)一、一對(duì)多,多對(duì)一、多對(duì)多三種關(guān)聯(lián)關(guān)系。

    OneToOne

  • targetEntity,作為關(guān)聯(lián)目標(biāo)的實(shí)體類(lèi)。

  • cascade,必須級(jí)聯(lián)到關(guān)聯(lián)目標(biāo)的操作。

  • ALL,級(jí)聯(lián)所有操作。

  • PERSIST,級(jí)聯(lián)保存操作。

  • MERGE,級(jí)聯(lián)修改操作。

  • REMOVE,級(jí)聯(lián)刪除操作。

  • REFRESH,級(jí)聯(lián)刷新操作。

  • DETACH,級(jí)聯(lián)分離操作。(2.0 版本開(kāi)始支持)

  • fetch,關(guān)聯(lián)是延遲加載還是必須立刻獲取。

  • optional,關(guān)聯(lián)是否為可選。

  • mappedBy,擁有關(guān)系的字段。僅在關(guān)聯(lián)的反側(cè)(非所有權(quán))指定此元素。

  • orphanRemoval,是否將刪除操作應(yīng)用于已從關(guān)系中刪除的實(shí)體,以及是否將刪除操作級(jí)聯(lián)到那些實(shí)體。

  • OneToMany

    targetEntity、cascade、fetch、mappedBy、orphanRemoval

    ManyToOne

    targetEntity、cascade、fetch、orphanRemoval

    ManyToMany

    targetEntity、cascade、fetch、mappedBy

    在以上關(guān)聯(lián)注解的使用過(guò)程中,還需要?@JoinColumn 指定實(shí)體關(guān)聯(lián)、元素集合的列。

    例如:@ManyToOne@JoinColumn(name="ADDR_ID")public Address getAddress() { return address; }@OneToMany@JoinColumn(name="CUST_ID")public?SetgetOrders()?{return?orders;}
    03 分析

    圖 A -?ER 圖

    本案例有四張數(shù)據(jù)庫(kù)表,分別為導(dǎo)購(gòu)員、商品數(shù)據(jù)、訂單主數(shù)據(jù),以及訂單明細(xì)數(shù)據(jù)。(如上圖所示)

    導(dǎo)購(gòu)員、商品數(shù)據(jù)是基礎(chǔ)數(shù)據(jù)表,即不主動(dòng)關(guān)聯(lián)其他的實(shí)體集。

    商品主數(shù)據(jù),包含兩種關(guān)聯(lián)關(guān)系。

  • 與導(dǎo)購(gòu)員之間的關(guān)系是多對(duì)一。即 @ManyToOne,注意這里只需要級(jí)聯(lián)刷新操作即可。

  • 與訂單明細(xì)數(shù)據(jù)的關(guān)系是一對(duì)多。即@OneToMany,注意這里需要級(jí)聯(lián)保存、修改、刪除、刷新所有的操作。

  • 商品明細(xì)數(shù)據(jù),也包含兩種關(guān)聯(lián)關(guān)系。

  • 與商品數(shù)據(jù)之間的關(guān)系是多對(duì)一。即 @ManyToOne,注意這里只需要級(jí)聯(lián)刷新操作即可。

  • 與訂單主數(shù)據(jù)的關(guān)系是多對(duì)一。即@ManyToOne,注意這里需要級(jí)聯(lián)保存、修改、刪除、刷新所有的操作。


  • 04?示例代碼

    導(dǎo)購(gòu)數(shù)據(jù)?UscGuideEntity

    package cn.live.opos.center.entity;// 省略 import/** * usc_guide. * * @author chenxinjie * @date 2020-08-01 */@Entity@Table(name = "usc_guide", uniqueConstraints = { @UniqueConstraint(columnNames = "no") })public class UscGuideEntity implements Serializable { private static final long serialVersionUID = -5648617800765002770L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid") @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator") @Column(name = "id", length = 36) private String id; @Column(name = "no", length = 20, nullable = false) private String no; @Column(name = "name", length = 40, nullable = false) private String name; @Column(name = "gender", columnDefinition = "int default 0", nullable = false) private int gender; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Temporal(TemporalType.TIMESTAMP) @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false) private Date ts;??//?省略?get/set?方法}

    商品數(shù)據(jù)?PscSkuEntity

    package cn.live.opos.center.entity;// 省略 import@Entity@Table(name = "psc_sku", uniqueConstraints = { @UniqueConstraint(columnNames = "sku") })public class PscSkuEntity implements Serializable { private static final long serialVersionUID = 8904367725209990433L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid") @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator") @Column(name = "id", length = 36) private String id; @Column(name = "sku", length = 50, nullable = false) private String sku; @Column(name = "product_no", length = 40, nullable = false) private String productNo; @Column(name = "product_name", length = 100, nullable = false) private String productName; @Column(name = "color_no", precision = 4, scale = 0, nullable = false) private int colorNo; @Column(name = "color_name", nullable = false) private String colorName; @Column(name = "size_no", precision = 4, scale = 0, nullable = false) private int sizeNo; @Column(name = "size_name", nullable = false) private String sizeName; @Column(name = "tag_price", precision = 10, scale = 0, nullable = false) private int tagPrice; @Column(name = "retail_price", precision = 10, scale = 0, nullable = false) private int retailPrice; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Temporal(TemporalType.TIMESTAMP) @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false) private Date ts; // 省略 get/set 方法}

    訂單主數(shù)據(jù)?OscOrderEntity

    package cn.live.opos.center.entity;// 省略 import@Entity@EntityListeners(AuditingEntityListener.class)@Table(name = "osc_order", uniqueConstraints = { @UniqueConstraint(columnNames = "order_no") })public class OscOrderEntity implements Serializable { private static final long serialVersionUID = -4409502876337140593L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid") @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator") @Column(name = "id", length = 36) private String id; @Column(name = "order_no", length = 40, nullable = false) private String orderNo; @CreatedDate @JsonFormat(pattern = "yyyy-MM-dd") @Temporal(TemporalType.DATE) @Column(name = "order_date", nullable = false) private Date orderDate; /** * 1: sell of goods. 2: return of goods. */ @Column(name = "order_type", nullable = false) private int orderType; @Column(name = "order_status", nullable = false) private int orderStatus; @Column(name = "num", precision = 5, scale = 0, nullable = false) private int num; @Column(name = "total", precision = 10, scale = 0, nullable = false) private int total; @Column(name = "guide_no", length = 20, nullable = false) private String guideNo; @LastModifiedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Temporal(TemporalType.TIMESTAMP) @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false) private Date ts; @OneToMany(targetEntity = OscOrderItemEntity.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "order_no", referencedColumnName = "order_no", insertable = false, updatable = false) private List orderItems; @ManyToOne(targetEntity = UscGuideEntity.class, cascade = CascadeType.REFRESH) @JoinColumn(name = "guide_no", referencedColumnName = "no", insertable = false, updatable = false) private UscGuideEntity guideEntity; // 省略 get/set 方法}

    訂單明細(xì)數(shù)據(jù)?OscOrderItemEntity

    package cn.live.opos.center.entity;// 省略 import@Entity@EntityListeners(AuditingEntityListener.class)@Table(name = "osc_order_item", uniqueConstraints = { @UniqueConstraint(columnNames = { "order_no", "sku" }) })public class OscOrderItemEntity implements Serializable { private static final long serialVersionUID = -7331381906879927968L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid") @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator") @Column(name = "id", length = 36) private String id; @Column(name = "order_no", length = 40, nullable = false) private String orderNo; @Column(name = "sku", length = 50, nullable = false) private String sku; @Column(name = "num", precision = 5, scale = 0, nullable = false) private int num; @Column(name = "tag_price", precision = 10, scale = 0, nullable = false) private int tagPrice; @Column(name = "retail_price", precision = 10, scale = 0, nullable = false) private int retailPrice; @Column(name = "total", precision = 10, scale = 0, nullable = false) private int total; @LastModifiedDate @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Temporal(TemporalType.TIMESTAMP) @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false) private Date ts; @ManyToOne(targetEntity = OscOrderEntity.class, cascade = CascadeType.ALL) @JoinColumn(name = "order_no", referencedColumnName = "order_no", insertable = false, updatable = false) private OscOrderEntity orderEntity; @ManyToOne(targetEntity = PscSkuEntity.class, cascade = CascadeType.REFRESH) @JoinColumn(name = "sku", referencedColumnName = "sku", insertable = false, updatable = false) private PscSkuEntity skuEntity;??// 省略 get/set 方法}

    05 效果

    使用 JPA 查詢一個(gè)訂單主數(shù)據(jù),JPA 會(huì)自動(dòng)將配置好的其他表的數(shù)據(jù)實(shí)體自動(dòng)查詢出來(lái)。

    也就是,省略了查詢導(dǎo)購(gòu)員、訂單明細(xì)數(shù)據(jù)、商品數(shù)據(jù)三條?SQL 語(yǔ)句。

    PS. 完整示例代碼,見(jiàn)?https://github.com/FoamValue/oPos.git


    06?小結(jié)

    今天先寫(xiě)到這里。

    夜深了,讓我們下周再見(jiàn)。?

    這個(gè)周末,又一次成功“強(qiáng)迫”自己學(xué)習(xí)。

    感謝各位小伙伴的閱讀,這里是一個(gè)技術(shù)人的學(xué)習(xí)與分享。

    總結(jié)

    以上是生活随笔為你收集整理的jpa onetoone_拥抱开源从表设计到 JPA 实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。