欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Data?JPA?實(shí)體類中常用注解說明

 更新時(shí)間:2021年11月22日 15:15:01   作者:半雨微涼  
這篇文章主要介紹了Spring?Data?JPA?實(shí)體類中常用注解說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

javax.persistence 介紹

Spring Data JPA 采用約定大于配置的思想,默認(rèn)了很多東西

JPA是存儲業(yè)務(wù)實(shí)體關(guān)聯(lián)的實(shí)體來源,它顯示定義了如何定義一個(gè)面向普通Java對象(POJO)作為實(shí)體,以及如何與管理關(guān)系實(shí)體提供一套標(biāo)準(zhǔn)

javax.persistence位于hibernate-jpa-**.jar 包里面

jpa類層次結(jié)構(gòu):

JPA類層次結(jié)構(gòu)的顯示單元:

單元 描述
EntityManagerFactory 一個(gè)EntityManager的工廠類,創(chuàng)建并管理多個(gè)EntityManager實(shí)例
EntityManager 一個(gè)接口,管理持久化操作的對象,工廠原理類似工廠的查詢實(shí)例
Entity 實(shí)體是持久性對象,是存儲在數(shù)據(jù)庫中的記錄
EntityTransaction 與EntityManager是一對一的關(guān)系,對于每一個(gè)EntityManager的操作由EntityTransaction類維護(hù)
Persistence 這個(gè)類包含靜態(tài)方法來獲取EntityManagerFactory實(shí)例
Query 該接口由每個(gè)JPA供應(yīng)商實(shí)現(xiàn),能夠獲得符合標(biāo)準(zhǔn)的關(guān)系對象

基本注解

@Entity

@Entity定義對象將會成為被JPA管理的實(shí)體,將映射到指定的數(shù)據(jù)庫表

public @interface Entity {
    String name() default "";
}

@Table

@Table指定數(shù)據(jù)庫的表名

public @interface Table {
    // 表的名字,可選,默認(rèn)實(shí)體類名為表的名稱(駝峰命名規(guī)則)
    String name() default "";
    // 此表的catlog,可選
    String catalog() default "";
    // 此表所在的schema,可選
    String schema() default "";
    // 唯一性約束,只有在創(chuàng)建表的時(shí)候有用,默認(rèn)不需要
    UniqueConstraint[] uniqueConstraints() default {};
    // 索引,只有創(chuàng)建表的時(shí)候有用,默認(rèn)不需要
    Index[] indexes() default {};
}

@Id

定義屬性為數(shù)據(jù)庫中的主鍵,一個(gè)實(shí)體必須有一個(gè)

@IdClass

@IdClass利用外部類的聯(lián)合主鍵

public @interface IdClass {
     // 聯(lián)合主鍵的類
    Class value();
}
  • 作為聯(lián)合主鍵類,需要滿足以下要求:
  • 必須實(shí)現(xiàn)Serializable
  • 必須有默認(rèn)的public無參構(gòu)造方法
  • 必須覆蓋equals和hashCode方法(EntityManager通過find方法查找Entity時(shí)是根據(jù)equals來判斷的)

用法:

(1)假設(shè)user_article表中的聯(lián)合主鍵是 title 與create_user_id,聯(lián)合主鍵類代碼如下:

@Data
public class UserArticleKey implements Serializable {
    private String title;
    private Long createUserId;
    public UserArticleKey() {
    }
    public UserArticleKey(String title, String content, Long createUserId) {
        this.title = title;
        this.createUserId = createUserId;
    }
}

(2)user_article表實(shí)體類如下:

@Entity
@IdClass(value = UserArticleKey.class)
@Data
public class UserArticle {
    private Integer id;
    @Id
    private String title;
    @Id
    private Long createUserId;
}

(3) repository 類如下:

public interface ArticleRepository extends JpaRepository<UserArticle, UserArticleKey> {
}

(4)調(diào)用代碼如下:

@Test
public void testUnionKey(){
    Optional<UserArticle> userArticle = this.articleRepository.findById(new UserArticleKey("新聞",1L));
    if (userArticle.isPresent()){
        System.out.println(userArticle.get());
    }
}

@GenerateValue

主鍵生成策略

public @interface GeneratedValue {
    // Id 的生成策略
    GenerationType strategy() default GenerationType.AUTO;
    // 通過 Sequence生成Id, 常見Oracle生成規(guī)則,需要配合@SequenceGenerator使用
    String generator() default "";
}

GenerationType

public enum GenerationType {
    // 通過表產(chǎn)生主鍵,框架由表模擬序列產(chǎn)生主鍵(有益于數(shù)據(jù)庫移植)
    TABLE,
    // 通過序列產(chǎn)生主鍵,通過@SequenceGenerator注解指定序列名,不支持MySQL
    SEQUENCE,
    // 采用數(shù)據(jù)ID自增長,一般用于MySQL
    IDENTITY,
    // JPA自動適配的策略,默認(rèn)選項(xiàng)
    AUTO;
    private GenerationType() {
    }
}

@Basic

屬性是到數(shù)據(jù)表的字段的映射,實(shí)體類上的字段沒有注解時(shí)默認(rèn)為@Basic

public @interface Basic {
    // 可選,默認(rèn)為立即加載(EAGER),LZAY延遲加載(應(yīng)用在大字段上)
    FetchType fetch() default FetchType.EAGER;
    // 可選,設(shè)置這個(gè)字段是否可為null,默認(rèn) true
    boolean optional() default true;
}

@Transient

表示該屬性并非一個(gè)到數(shù)據(jù)庫表的字段的映射,表示非持久化屬性,與@Basic作用相反,JPA映射的時(shí)候會忽略@Transient標(biāo)記的字段

@Column

定義屬性對應(yīng)數(shù)據(jù)庫中的列名

public @interface Column {
    // 是語句庫中表的列名, 默認(rèn)字段名和屬性名一樣, 可選
    String name() default "";
    // 是否唯一,默認(rèn) false, 可選
    boolean unique() default false;
    // 是否允許空, 默認(rèn) true, 可選
    boolean nullable() default true;
    // 執(zhí)行insert操作的時(shí)候是否包含此字段,默認(rèn) true, 可選
    boolean insertable() default true;
    // 執(zhí)行update操作的時(shí)候是否包含此字段,默認(rèn) true, 可選
    boolean updatable() default true;
    // 該字段在數(shù)據(jù)庫中的實(shí)際類型
    String columnDefinition() default "";
    // 當(dāng)映射多個(gè)表時(shí),指在哪張表的字段,默認(rèn)為主表
    String table() default "";
    // 字段長度,字段類型為VARCHAR時(shí)有效
    int length() default 255;
    // 精度,當(dāng)字段類型為double時(shí)候, precision表示數(shù)值總長度
    int precision() default 0;
    // 精度, 當(dāng)字段類型為double時(shí)候, scale表示小數(shù)位數(shù)
    int scale() default 0;
}

@Temporal

用來設(shè)置Date 類型的屬性映射到對應(yīng)精度的字段

  • @Temporal(Temporal.DATE) 映射為日期
  • @Temporal(Temporal.TIME) 映射為日期(只有時(shí)間)
  • @Temporal(Temporal.TIMESTAMP) 映射為日期(日期+時(shí)間)

@Enumerated

映射menu枚舉類型的字段

源碼:

public @interface Enumerated {
    // 映射枚舉的類型
    EnumType value() default EnumType.ORDINAL;
}
public enum EnumType {
    // 映射枚舉字段的下標(biāo)
    ORDINAL,
    // 映射枚舉的name
    STRING;
}

如果使用 ORDINAL 在數(shù)據(jù)庫中則會存儲 0,1,2,3 這是一個(gè)索引值,這個(gè)索引值是由enum中元素的位置決定,如果enum中元素位置出現(xiàn)不正確的變動

很可能與數(shù)據(jù)庫中的數(shù)據(jù)無法對應(yīng),建議使用 STRING

用法:

@Entity(name = "t_user")
@Data
@Table
public class SystemUser implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Basic
    private String uname;
    private String email;
    private String address;
    @Enumerated(EnumType.STRING)
    @Column(name = "user_gender")
    private Gender sex;
    public enum Gender{
        MALE("男性"),
        FEMALE("女性")
        ;
        private String value;
        Gender(String value) {
            this.value = value;
        }
    }
}

@Lob

映射成數(shù)據(jù)庫支持的大對象類型

  • Clob(Character Large Objects) 類型是長字符串類型java.sql.Clob、Character[]、char[]和String將被映射為Clob類型
  • Blob(Binary Large Objects) 類型是字節(jié)型,java.sql.Blob,Byte[]、byte[]和實(shí)現(xiàn)了Serializable接口的類型將被映射為Blob類型
  • Clob、Blob占用內(nèi)存空間較大,一般配合@Basic(fetch=FetchType.LAZY)將其設(shè)置為延遲加載

@NamedNativeQueries、@NamedNativeQuerie、@SqlResultSetMappings、@SqlResultSetMapping、@ColumnResult

這幾個(gè)注解一般配合使用,實(shí)際情況中不會自定義這些配置

@NamedNativeQueries({
        @NamedNativeQuery(
                name = "getUsers",
                query = "select id,title,create_user_id,create_date from user_article order by create_date desc",
                resultSetMapping = "userArticleMap"
        )
})
@SqlResultSetMappings({
        @SqlResultSetMapping(
                name = "userArticleMap",
                entities = {},
                columns = {
                        @ColumnResult(name = "id"),
                        @ColumnResult(name = "title"),
                        @ColumnResult(name = "createUserId"),
                        @ColumnResult(name = "createDate"),
                }
        )
})
@Entity
@IdClass(value = UserArticleKey.class)
@Data
public class UserArticle {
    @Column
    private Integer id;
    @Id
    private String title;
    @Id
    private Long createUserId;
    private Date createDate;
}

關(guān)聯(lián)關(guān)系注解

@JoinColumn 定義外鍵關(guān)聯(lián)的字段名稱

主要配合 @OneToOne、@ManyToOne、@OneToMany一起使用,單獨(dú)使用沒有意義

@JoinColumns 定義多個(gè)字段的關(guān)聯(lián)關(guān)系

public @interface JoinColumn {
    // 目標(biāo)表的字段名,必填
    String name() default "";
    // 本實(shí)體類的字段名, 非必填, 默認(rèn)本表ID
    String referencedColumnName() default "";
    // 外鍵字段是否唯一, 可選
    boolean unique() default false;
    // 外鍵字段是否允許為空, 可選
    boolean nullable() default true;
    // 是否跟隨一起新增, 可選
    boolean insertable() default true;
    // 是否跟隨一起更新, 可選
    boolean updatable() default true;
    // 生成DDL的時(shí)候使用的SQL片段 可選
    String columnDefinition() default "";
    // 包含列的表的名稱 , 可選
    String table() default "";
    // 外鍵約束類別, 默認(rèn)為 默認(rèn)約束行為, 可選
    ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}

@OneToOne 一對一關(guān)聯(lián)關(guān)系

public @interface OneToOne {
    // 關(guān)系目標(biāo)實(shí)體, 默認(rèn)為void.class, 可選
    Class targetEntity() default void.class;
    // 級聯(lián)操作策略, PERSIST(級聯(lián)新增)、REMOVE(級聯(lián)刪除)、REFRESH(級聯(lián)刷新)、MERGE(級聯(lián)更新)、ALL(全選)
    // 默認(rèn)表不會產(chǎn)生任何影響
    CascadeType[] cascade() default {};
    // 數(shù)據(jù)獲取方式,EAGER(立即加載)、LAZY(延遲加載)
    FetchType fetch() default EAGER;
    // 是否允許空
    boolean optional() default true;
    // 關(guān)聯(lián)關(guān)系被誰維護(hù),非必填,一遍不需要特別指定
    // mappedBy不能與@JoinColumn或者@JoinTable同時(shí)使用
    // mappedBy的值是指另一方的實(shí)體里面屬性的字段,而不是數(shù)據(jù)庫字段,也不是實(shí)體的對象的名字,即另一方配置了@JoinColumn或者@JoinTable注解的屬性的字段名稱
    String mappedBy() default "";
    
    // 是否級聯(lián)刪除,和CascadeType.REMOVE 效果一樣,任意配置一種即可生效
    boolean orphanRemoval() default false;
}

用法:

@OneToOne
// name 為當(dāng)前實(shí)體對應(yīng)數(shù)據(jù)庫表中的字段名
// referencedColumnName 為 SystemUser 實(shí)體中@Id標(biāo)記的字段對應(yīng)的數(shù)據(jù)庫字段名
@JoinColumn(name = "create_user_id",referencedColumnName = "id")
private SystemUser createUser = new SystemUser();

雙向關(guān)聯(lián):

@OneToOne(mappedBy = "createUser")
private UserArticle article = new UserArticle();

等價(jià)于mappedBy:

@OneToOne
@JoinColumn(name = "user_article_id",referencedColumnName = "id")
private UserArticle article = new UserArticle();

@OneToMany 與 @ManyToOne 一對多與多對一關(guān)聯(lián)關(guān)系

OneToMany與ManyToOne可以相對存在,也可只存在一方

public @interface OneToMany {
    Class targetEntity() default void.class;
    // 級聯(lián)操作策略
    CascadeType[] cascade() default {};
    // 數(shù)據(jù)獲取方式
    FetchType fetch() default LAZY;
    // 關(guān)系被誰維護(hù),單項(xiàng)的
    String mappedBy() default "";
    // 是否級聯(lián)刪除
    boolean orphanRemoval() default false;
}
public @interface ManyToOne {
    Class targetEntity() default void.class;
    // 級聯(lián)操作策略
    CascadeType[] cascade() default {};
    // 數(shù)據(jù)獲取方式
    FetchType fetch() default LAZY;     // 關(guān)聯(lián)是否可選。如果設(shè)置,若要為false,則必須始終存在非null關(guān)系。
    boolean optional() default true;
}

@ManyToOne 映射的是一個(gè)實(shí)體對象

@Entity
@Data
public class UserArticle {
    @Column
    private Integer id;
    @Id
    private String title;
    @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @JoinColumn(name = "create_user_id",referencedColumnName = "id")
    private SystemUser systemUser = new SystemUser();
    private Date createDate;
}

@OneToMany 映射的是一個(gè)是列表

@Entity(name = "t_user")
@Data
@Table
public class SystemUser implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Basic
    private String uname;
    private String email;
    private String address;
    @Enumerated(EnumType.STRING)
    private Gender sex;
@OneToMany
// name 當(dāng)前表id
// create_user_id 目標(biāo)表的關(guān)聯(lián)字段
@JoinColumn(name = "id",referencedColumnName = "create_user_id")
private List<UserArticle> articleList = new ArrayList<>();
    public enum Gender{
        MALE("男性"),
        FEMALE("女性")
        ;
        private String value;
        Gender(String value) {
            this.value = value;
        }
    }
}

@OrderBy 排序關(guān)聯(lián)查詢

與@OneToMany一起使用

public @interface OrderBy {
    /**
     * 要排序的字段格式如下:
     *    orderby_list::= orderby_item [,orderby_item]*
     *    orderby_item::= [property_or_field_name] [ASC | DESC]
     * 字段可以是實(shí)體屬性,也可以是數(shù)據(jù)字段,默認(rèn)ASC
     */
    String value() default "";
}

用法:

@OneToMany
@JoinColumn(name = "id",referencedColumnName = "create_user_id")
@OrderBy("createDate DESC") // createDate 是 UserArticle 的實(shí)體屬性
private List<UserArticle> articleList = new ArrayList<>();
 

@JoinTable 關(guān)聯(lián)關(guān)系表

對象與對象之間有關(guān)聯(lián)關(guān)系表的時(shí)候就用到,@JoinTable, 與@ManyToMany一起使用

public @interface JoinTable {
    // 中間關(guān)聯(lián)關(guān)系表名
    String name() default "";
    // 表的 catalog
    String catalog() default "";
    // 表的 schema
    String schema() default "";
    // 主連接表的字段
    JoinColumn[] joinColumns() default {};
    // 被連接表的字段
    JoinColumn[] inverseJoinColumns() default {};
    // 主連接外鍵約束類別
    ForeignKey foreignKey() default @ForeignKey(PROVIDER_DEFAULT);
    // 被連接外鍵約束類別
    ForeignKey inverseForeignKey() default @ForeignKey(PROVIDER_DEFAULT);
    // 唯一約束
    UniqueConstraint[] uniqueConstraints() default {};
    // 表的索引
    Index[] indexes() default {};
}

用法:

@Entity
// 主連接表 blog
public class Blog {
    @ManyToMany
    @JoinTable(
            name = "blog_tag_relation", // 關(guān)系表名稱
            joinColumns = @JoinColumn(name = "blog_id",referencedColumnName = "id"), // 主連接表配置
            inverseJoinColumns = @JoinColumn(name = "tag_id",referencedColumnName = "id") // 被連接表配置
    )
    // tag 是被連接表
    private List<Tag> tags = new ArrayList<>();
}

關(guān)于雙向多對多:

雙向多對多需要建立 @JoinTable的實(shí)體里, 在被連接表中的@ManyToMany中使用mappedBy="BlogTagRelation"進(jìn)行配置

LeftJoin 與 Inner Join 可以提高查詢效率

當(dāng)使用@ManyToMany、@ManyToOne、@OneToMany、@OneToOne關(guān)聯(lián)時(shí)候,SQL真正執(zhí)行的時(shí)候,由一條主表查詢和N條子表查詢組成

會產(chǎn)生N+1問題

為了簡單的提高查詢效率,使用EntityGraph可以解決N+1條SQL的問題

@EntityGraph

@EntityGraph、@NamedEntityGraph用來提高查詢效率(很好的解決了N+1條SQL的問題),兩者需要配合使用,缺一不可

實(shí)體類:

@NamedEntityGraph(
        name = "Blog.tags", attributeNodes = {
        @NamedAttributeNode("tags")
}
)
@Entity
// 主連接表 blog
public class Blog {
    @ManyToMany
    @JoinTable(
            name = "blog_tag_relation", // 關(guān)系表名稱
            joinColumns = @JoinColumn(name = "blog_id", referencedColumnName = "id"), // 主連接表配置
            inverseJoinColumns = @JoinColumn(name = "tag_id", referencedColumnName = "id") // 被連接表配置
    )
    // tag 是被連接表
    private List<Tag> tags = new ArrayList<>();
}

repository:

public interface BlogRepository extends JpaRepository<Blog,Long> {
    @Override
    @EntityGraph(value = "Blog.tags")
    List<Blog> findAll();
}

關(guān)于關(guān)系查詢的一些注意事項(xiàng)

所有注解要么全配置在字段上,要么配置在get方法上,不能混用,會無法啟動

所有的關(guān)聯(lián)都是支持單向關(guān)聯(lián)和雙向關(guān)聯(lián)的,JSON序列化的時(shí)候使用雙向注解會產(chǎn)生死循環(huán),需要手動轉(zhuǎn)化一次或使用@JsonIgnore

在所有的關(guān)聯(lián)查詢中,表一般是不需要簡歷外鍵索引的,@mappedBy的使用需要注意

級聯(lián)刪除比較危險(xiǎn),建議考慮清楚或完全掌握

不同的關(guān)聯(lián)關(guān)系的配置,@JoinColumn里面的name,referencedColumnName代表的意思是不一樣的

當(dāng)配置這些關(guān)聯(lián)關(guān)系的時(shí)候建議直接在表上把外鍵關(guān)系簡歷好,然后用開發(fā)工具直接生成,這樣可以減少調(diào)試時(shí)間

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot依賴及其作用分析

    SpringBoot依賴及其作用分析

    這篇文章主要介紹了SpringBoot依賴及其作用,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java Calendar日歷類的使用介紹

    Java Calendar日歷類的使用介紹

    Candendar類是一個(gè)抽象類,提供了一些獲取當(dāng)前時(shí)間,或者指定的時(shí)間的字段和一些方法,我們可以通過一些方法與字段對他進(jìn)行獲取當(dāng)前天或者當(dāng)月的一些信息
    2022-09-09
  • spring-mybatis與原生mybatis使用對比分析

    spring-mybatis與原生mybatis使用對比分析

    這篇文章主要介紹了spring-mybatis與原生mybatis使用對比分析,需要的朋友可以參考下
    2017-11-11
  • Spring中的@Qualifier注解和@Resource注解區(qū)別解析

    Spring中的@Qualifier注解和@Resource注解區(qū)別解析

    這篇文章主要介紹了Spring中的@Qualifier注解和@Resource注解區(qū)別解析,@Qualifier注解的用處是當(dāng)一個(gè)接口有多個(gè)實(shí)現(xiàn)的時(shí)候,為了指名具體調(diào)用哪個(gè)類的實(shí)現(xiàn),@Resource注解可以通過 byName命名和byType類型的方式注入,需要的朋友可以參考下
    2023-11-11
  • java中l(wèi)ist的用法和實(shí)例講解

    java中l(wèi)ist的用法和實(shí)例講解

    這篇文章主要介紹了java中l(wèi)ist的用法和實(shí)例講解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • springboot動態(tài)調(diào)整日志級別的操作大全

    springboot動態(tài)調(diào)整日志級別的操作大全

    這篇文章主要介紹了springboot動態(tài)調(diào)整日志級別的方法,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • 使用maven war包打包去除jar包瘦身

    使用maven war包打包去除jar包瘦身

    這篇文章主要介紹了使用maven war包打包去除jar包瘦身操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java反射如何修改private final成員變量值

    Java反射如何修改private final成員變量值

    這篇文章主要介紹了Java反射如何修改private final成員變量值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 一文詳解如何在SpringMVC的視圖中渲染模型數(shù)據(jù)

    一文詳解如何在SpringMVC的視圖中渲染模型數(shù)據(jù)

    SpringMVC是一個(gè)基于Spring框架的Web框架,它提供了一種方便的方式來處理 HTTP 請求和響應(yīng),在SpringMVC中,視圖是用來渲染模型數(shù)據(jù)的組件,它們負(fù)責(zé)將模型數(shù)據(jù)轉(zhuǎn)換為HTML、JSON、XML等格式的響應(yīng),在本文中,我們將討論如何在SpringMVC中的視圖中渲染模型數(shù)據(jù)
    2023-07-07
  • Java之單例設(shè)計(jì)模式示例詳解

    Java之單例設(shè)計(jì)模式示例詳解

    這篇文章主要介紹了Java之單例設(shè)計(jì)模式示例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07

最新評論