Spring-Data-Jpa中的常用註解詳解及其用法

** 1 @Query註解詳解及其用法**

說明:本文的寫作構建在我的公衆號文章SpringBoot之路(二)使用用Spring-Data-JPA訪問數據庫進行基本的CRUD操作這篇文章的基礎之上。

@Query註解在spring-data-jpa中可用來定製自定義sql語句的數據庫增刪改查操作,使用起來也是非常方便

1.1 源碼分析

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@QueryAnnotation
@Documented
public @interface Query {
    /**
    *指定JPAL查詢語句,nativeQuery=true時是原生的SQL語句
    */
    String value() default "";
    
	/**
	*指定count的 JPQL語句,如果不指定將根據query自動生成;
	*nativeQuery=true時是原生的SQL語句
	*/
    String countQuery() default "";
    /**
    *根據哪個字段來count,一般默認即可
    */
    String countProjection() default "";
	/**
	*默認爲false,表示不是原生的SQL語句
	*/
    boolean nativeQuery() default false;
    
    /**
    *可以指定一個query的名字,必須是唯一的,
    *如果不指定,默認的生產規則是{$domainClass}.{$queryMethodName}
    */
    String name() default "";
	/**
	*指定一個count的query名字,必須是唯一的
	*如果不指定,默認的生產規則是{$domainClass}.{$queryMethodName}.count
	
	*/
    String countName() default "";
}

1.2 @Query的用法

使用命名查詢爲實體聲明查詢是一種有效的方法,對於少量查詢 很有效;一般只需要關心@Query裏面的value和nativeQuery的值;使 用聲明式JPQL查詢有一個好處,就是啓動的時候就知道語法正確與否。

示例:聲名一個@Query註解裝飾的方法在UserRepository上

(1)@Query註解中自定義select語句

@Query(value="select user_id,user_name,password,user_sex,user_name_cn,user_role,tel_num," +      "email,reg_date,birth_day,created_by,created_time,last_updated_by,last_updated_time from user_info where user_role=?1",nativeQuery = true)
    List<UserInfo> findByUserRole(String userRole);
/**使用@Query裝飾的方法自定義SQL查詢時
*必須修改nativeQuery = true,表示這是一個原生SQL,
*否則項目啓動時就會報錯
*/

(2)@Query註解中自定義update語句

@Modifying
@Query(value="update user_info set email=?2 where user_name=?1",nativeQuery = true)
    Integer updateEmailByUserName(String username,String email);

注意:update操作必須在@Query註解上方加上@Modifying註解,否則執行sql語句時會報無法提取結果集異常

1.3 like查詢,注意不會自動加上%關鍵字

 @Query(value="select user_id,user_name,user_sex,"+ "user_name_cn,user_role,tel_num,email,reg_date from user_info where user_name like ?1 %",nativeQuery=true)
    List<UserInfo> findByLikeUserName(String userName);
//注意以上1與%之間不能有空格

注意: nativeQuery不支持直接Sort的參數查詢

nativeQuery的錯誤寫法,下面這個寫法會使項目啓動時報錯:

@Query(value="select * from user_info where user_name like ?1%",nativeQuery = true)
    List<UserInfo> findByUserName(String userName, Sort sort);

1.4 本節測試

以1.2中的在@Query註解中自定義update語句爲例,完成Service層和Controller層代碼

Service層代碼

//UserService 接口中添加抽象方法
Integer updateEmailByUsername(String username,String email);

//UserServiceImpl類中實現方法,注意數據庫增、刪、改方法都要加上@Transactional事務註解
    @Override
    @Transactional
    public Integer  updateEmailByUsername(String username, String email) {

        return userRepository.updateEmailByUserName(username,email);

    }

controller層代碼

@PutMapping("/email/{username}/{email}")
    public ServiceResponse<Integer> updateUserEmailByUsername(@PathVariable("username") String username,@PathVariable("email") String email){

        ServiceResponse<Integer> response = new ServiceResponse<>();
        log.info("username={},email={}",username,email);
        Integer count = userInfoService.updateEmailByUsername(username,email);
        response.setData(count);
        return response;
    }

這時就可以通過postman測試效果了

// 請求方法與URL
PUT http://localhost:8088/apiBoot/user/email/LiSi/lisi1989@163.com

//返回結果
{
    "status": 200,
    "message": "ok",
    "data": 1
}

//此時再來調用根據用戶名查看用戶信息接口
GET ttp://localhost:8088/apiBoot/user/userInfos/userName?userName=LiSi
//返回結果
{
    "status": 200,
    "message": "ok",
    "data": [
        {
            "userId": 2,
            "userName": "LiSi",
            "password": "89d462491dd4f9e5f2125485a835540c",
            "userNameCn": "李四",
            "userSex": "M",
            "userRole": "Admin",
            "telNum": 13100001002,
            "email": "[email protected]",
            "regDate": "2018-06-10",
            "birthDay": "1989-07-12",
            "createdBy": "system",
            "createdTime": "2020-03-13 23:48:30",
            "lastUpdatedBy": "admin",
            "lastUpdatedTime": "2020-04-26 11:28:29"
        }
    ]
}

從返回結果的email字段可發現用戶的郵箱已經發生了改變

nativeQuery排序的正確寫法

@Query(value="select * from user_info where user_name like ?1% order by ?2 desc",nativeQuery = true)
    List<UserInfo> findByUserNameAndOrderBy(String userName, String sort);

使用@Query註解查詢時的不足就是不支持動態條件查詢

2 javax.persistence概況介紹

雖然Spring Data JPA已經幫我們對數據的操作封裝得很好了, 約定大於配置思想,幫我們默認了很多東西。JPA(Java持久性API) 是存儲業務實體關聯的實體來源。它顯示瞭如何定義一個面向普通 Java對象(POJO)作爲一個實體,以及如何與管理關係實體提供一套 標準。因此,javax.persistence下面的有些註解還是必須要去了解的,以便於更好地提高工作效率.

(1)javax.persistence位於org.hibernate:hibernate-core.jar包裏面,可 以通過Intellij Idea的maven插件直接分析一下maven的依賴,也可以用 $ mvn dependency:tree分析,例如:

[INFO] |  +- org.hibernate:hibernate-core:jar:5.3.9.Final:compile
[INFO] |  |  +- javax.persistence:javax.persistence-api:jar:2.2:compile
[INFO] |  |  +- org.javassist:javassist:jar:3.23.1-GA:compile
[INFO] |  |  +- antlr:antlr:jar:2.7.7:compile
[INFO] |  |  +- org.jboss:jandex:jar:2.0.5.Final:compile
[INFO] |  |  +- org.dom4j:dom4j:jar:2.1.1:compile
[INFO] |  |  \- org.hibernate.common:hibernate-commons-annotations:jar:5.0.4.Final:compile
[INFO] |  +- org.springframework.data:spring-data-jpa:jar:2.1.6.RELEASE:compile
[INFO] |  |  +- org.springframework.data:spring-data-commons:jar:2.1.6.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-orm:jar:5.1.6.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-tx:jar:5.1.6.RELEASE:compile
[INFO] |  \- org.springframework:spring-aspects:jar:5.1.6.RELEASE:compile

(2)通過Intellij Idea的Diagram來看一下此模塊類的關鍵關 系,如圖所示:
javax.persistent模塊中的關鍵接口和類關係圖

(3)下圖顯示了JPA的類的層次結構,包括核心類和JPA接口。
jpa中的核心接口和類

(4)JPA類層次結構的顯示單元

單元 描述
EntityManagerFactory 一個EntityManager的工廠類,創建並管理多個EntityManager實例
EntityManager 一個接口,管理持久化操作對象,工作原理類似工廠的查詢實例
Entity 實體是持久性對象,是存儲在數據庫中的記錄
EntityTransaction 與EntityManager是一對一的關係,對於每個EntityManager,操作是由EntityTransaction來維護的
Persistence 這個類包含使用靜態方法獲取EntityManagerFactory的實例
Query 該接口由每個JPA供應商實現,能夠獲得符合標準的關係對象

上述的類和接口用於存儲實體到數據庫的一個記錄,幫助程序員 通過減少自己編寫的代碼將數據存儲到數據庫中,使他們能夠專注於 更重要的業務活動代碼,如數據庫表映射的類編寫代碼。

3 javax.persistence包下的基本註解

javax.persistence包下基本註解包括@Entity、@Table、@Id、@IdClass、 @GeneratedValue、@Basic、@Transient、@Column、@Temporal、 @Enumerated、@Lob。

3.1 @Entity

先看一個Blog的示例,其中實體的配置如下:

@Entity
@Table(name="user_blog",schema = "mysql")
@NoArgsConstructor
public class UserBlogEntity {

    @Id
    @Column(name="id",nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Setter
    @Getter
    private Integer Id;

    @Column(name="title",nullable = true,length = 200)
    @Setter
    @Getter
    private String title;

    @Basic
    @Column(name="create_user_id",nullable = true)
    private Integer createUserId;
	
    //由於blog_content字段使用blob類型時從數據庫查詢出的結果一直顯示亂碼,
    //因此本實例使用text類型代替blob類型,
    //在mysql數據庫中text類型的數據是一個大小寫不敏感的blob類型數據
    @Basic
    @Column(name="blog_content",nullable = true,length = 4000)
    @Setter
    @Getter
    private String blogContent;

    @Column(name="image",nullable = true)
    @Lob
    @Setter
    @Getter
    private String image;
    
    //日期屬性必須加上日期格式化註解com.fasterxml.jackson.annotation.JsonFormat,
    //防止序列化參數時報錯    
    @Column(name="create_time",nullable = true)
    @Temporal(TemporalType.DATE)
    @Setter
    @Getter
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 
    private Date createTime;
    
    @Transient
    @Setter
    @Getter
    private String transitSimple;
    
}

在數據庫中新建一張與UserBlogEntity實體類對應的表:

use mysql;
create table user_blog(
  `id` integer unique key,
   `create_user_id` integer,
   `title` varchar(200),
   `blog_content`  text,
   `image` varchar(500),
   `create_time` TIMESTAMP,
  primary key (`create_user_id`,`title`)
)engine=InnoDB default CHARSET=utf8;

@Entity定義對象將會成爲被JPA管理的實體,將映射到指定的數據庫表。

title` varchar(200),
   `blog_content`  text,
   `image` varchar(500),
   `create_time` TIMESTAMP,
  primary key (`create_user_id`,`title`)
)engine=InnoDB default CHARSET=utf8;

@Entity定義對象將會成爲被JPA管理的實體,將映射到指定的數 據庫表。

public @interface Entity {
    //默認是實體類的名字,全局唯一
    String name() default "";
}

3.2 @Table

@Table指定數據庫的表名

public @interface Table {
    //表名,可選,不填寫時默認爲實體類名
    String name() default "";
    //表的catalog
    String catalog() default "";
    //表所在的schema
    String schema() default "";
    //唯一約束,只有在創建表時有用,默認不需要
    UniqueConstraint[] uniqueConstraints() default {};
    //索引,只在創建表時有用,默認不需要
    Index[] indexes() default {};
}

3.3 @Id

@Id定義屬性爲數據庫的主鍵,一個實體裏面必須有一個

3.4 @IdClass

@IdClass利用外部類的聯合主鍵

public @interface IdClass {
    Class value();
}
  • 作爲符合主鍵類,要滿足以下幾點要求。

  • 必須實現Serializable接口。

  • 必須有默認的public無參數的構造方法。

  • 必須覆蓋equals和hashCode方法。equals方法用於判斷兩個對 象是否相同,EntityManger通過find方法來查找Entity時是根 據equals的返回值來判斷的。在本例中,只有對象的name和 email值完全相同或同一個對象時才返回true,否則返回 false。hashCode方法返回當前對象的哈希碼,生成的hashCode相同的概率越小越好,算法可以進行優化。

用法:假設UserBlog的聯合主鍵是createUserId和title,新增一個UserBlogKey的類,UserBlogkey.class代碼如下:

@NoArgsConstructor
@AllArgsConstructor
public class UserBlogKey implements Serializable {

    @Setter
    @Getter
    private Integer createUserId;

    @Setter
    @Getter
    private String title;
    
    //注意:作爲聯合主鍵的類需要重寫equals和hashCode方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserBlogKey that = (UserBlogKey) o;
        return Objects.equals(createUserId, that.createUserId) &&
                Objects.equals(title, that.title);
    }

    @Override
    public int hashCode() {
        return Objects.hash(createUserId, title);
    }

}

UserBlogRepository中的改動如下:

public interface UserBlogRepository extends JpaRepository<UserBlogEntity,UserBlogKey> {
   
}

@IdClass的用法實戰

(1)先寫兩個往User_Blog表中插入數據的接口和一個根據Id查詢UserBlogEntity的接口

service層代碼 UserBlogService.java

public interface UserBlogService {

    UserBlogEntity saveOne(UserBlogEntity userBlogEntity);

    List<UserBlogEntity> saveAll(List<UserBlogEntity> userBlogEntities);
    
    UserBlogEntity findById(UserBlogKey blogKey);
}

UserBlogServiceImpl.java

@Service
public class UserBlogServiceImpl implements UserBlogService {

    @Autowired
    private UserBlogRepository userBlogRepository;

    @Override
    @Transactional
    public UserBlogEntity saveOne(UserBlogEntity userBlogEntity) {

        return userBlogRepository.save(userBlogEntity);
    }

    @Override
    @Transactional
    public List<UserBlogEntity> saveAll(List<UserBlogEntity> userBlogEntities) {

        return userBlogRepository.saveAll(userBlogEntities);
    }
    
    @Override
    public UserBlogEntity findById(UserBlogKey blogKey) {

        return userBlogRepository.findById(blogKey).get();
    }
}

controller層代碼 UserBlogController.java

@RestController
@RequestMapping("/userBlog")
@Slf4j
public class UserBlogController {

    @Autowired
    private UserBlogService userBlogService;

    @PostMapping("/oneUserBlog")
    public ServiceResponse<UserBlogEntity> saveOneUserBlog(@RequestBody UserBlogEntity blogEntity){
        log.info("blogEntity={}", JSON.toJSON(blogEntity));
        
        ServiceResponse<UserBlogEntity> response = new ServiceResponse<>();
        
        UserBlogEntity data = userBlogService.saveOne(blogEntity);
        
        response.setData(data);
        
        return response;
    }

    @PostMapping("/batchUserBlog")
    public ServiceResponse<List<UserBlogEntity>> batchSaveUserBlog(@RequestBody List<UserBlogEntity> blogEntities){

        log.info("blogEntities={}", JSONArray.toJSONString(blogEntities,true));

        ServiceResponse<List<UserBlogEntity>> response = new ServiceResponse<>();

        List<UserBlogEntity> data = userBlogService.saveAll(blogEntities);

        response.setData(data);

        return response;
    }

    @GetMapping("/findOne")
    public ServiceResponse<UserBlogEntity> findByBlogKey(@RequestParam("createUserId") Integer createUserId,
                                                         @RequestParam("title") String title){
        log.info("createUserId={},title={}",createUserId,title);
        
        ServiceResponse<UserBlogEntity> response = new ServiceResponse<>();
        
        UserBlogEntity blogEntity = userBlogService.findById(new UserBlogKey(createUserId,title));
        
        response.setData(blogEntity);
        
        return  response;

    }

}

postman測試

(1) 插入一條數據

//請求方法與URL
POST http://localhost:8088/apiBoot/userBlog/oneUserBlog
//入參數據
{
	"id":1,
	"createUserId":1,
	"title":"spring-data-jpa從入到精通(一)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec24079a8164.png",
	"blogContent":"本博文講述了使用spring-data-jpa進行基本的CRUD操作",
	"createTime":"2020-05-31 11:11:00",
	"transitSimple": "test1"
}
//請求響應數據
{
    "status": 200,
    "message": "ok",
    "data": {
        "title": "spring-data-jpa從入到精通(一)",
        "createUserId": 1,
        "blogContent": "本博文講述了使用spring-data-jpa進行基本的CRUD操作",
        "image": "https://pic.ibaotu.com/game/title/20200518/5ec24079a8164.png",
        "createTime": "2020-05-31 11:11:00",
        "transitSimple": null,
        "id": 1
    }
}

(2)批量插入多條數據

//請求方法與URL
POST http://localhost:8088/apiBoot/userBlog/batchUserBlog
//入參數據
[{
	"id":2,
	"createUserId":1,
	"title":"spring-data-jpa從入到精通(二)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec240798e78c.png",
	"blogContent":"本博文對spring-data-jpa框架中的常用註解及其用法進行了實戰講述",
	"createTime":"2020-05-31 11:41:00",
	"transitSimple": "test2"
},{
	"id":3,
	"createUserId":1,
	"title":"spring-data-jpa從入到精通(三)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec240798e78c.png",
	"blogContent":"本博文主要講述了在spring-boot項目中使用spring-data-jpa進行聯表查詢及複雜的動態查詢的用法",
	"createTime":"2020-05-31 11:41:00",
	"transitSimple": "test3"
},{
   	"id":4,
	"createUserId":1,
	"title":"spring-data-jpa從入到精通(四)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
	"blogContent":"本博文主要講述了spring-data-jpa的擴展部分",
	"createTime":"2020-05-31 11:42:00",
	"transitSimple": "test4"
},{
	"id":5,
	"createUserId":2,
	"title":"Spring從入門到精通(一)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
	"blogContent":"Spring官網閱讀(一)容器及實例化",
	"createTime":"2020-05-31 11:42:00",
	"transitSimple": "test5"
},{
	"id":6,
	"createUserId":2,
	"title":"Spring從入門到精通(二)",
	"image":"https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
	"blogContent":"Spring官網閱讀(二)依賴注入及方法注入",
	"createTime":"2020-05-31 11:43:00",
	"transitSimple": "test6"
}]
//請求響應數據
{
    "status": 200,
    "message": "ok",
    "data": [
        {
            "title": "spring-data-jpa從入到精通(二)",
            "createUserId": 1,
            "blogContent": "本博文對spring-data-jpa框架中的常用註解及其用法進行了實戰講述",
            "image": "https://pic.ibaotu.com/game/title/20200518/5ec240798e78c.png",
            "createTime": "2020-05-31 11:41:00",
            "transitSimple": null,
            "id": 2
        },
        {
            "title": "spring-data-jpa從入到精通(三)",
            "createUserId": 1,
            "blogContent": "本博文主要講述了在spring-boot項目中使用spring-data-jpa進行聯表查詢及複雜的動態查詢的用法",
            "image": "https://pic.ibaotu.com/game/title/20200518/5ec240798e78c.png",
            "createTime": "2020-05-31 11:41:00",
            "transitSimple": null,
            "id": 3
        },
        {
            "title": "spring-data-jpa從入到精通(四)",
            "createUserId": 1,
            "blogContent": "本博文主要講述了spring-data-jpa的擴展部分",
            "image": "https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
            "createTime": "2020-05-31 11:42:00",
            "transitSimple": null,
            "id": 4
        },
        {
            "title": "Spring從入門到精通(一)",
            "createUserId": 2,
            "blogContent": "Spring官網閱讀(一)容器及實例化",
            "image": "https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
            "createTime": "2020-05-31 11:42:00",
            "transitSimple": null,
            "id": 5
        },
        {
            "title": "Spring從入門到精通(二)",
            "createUserId": 2,
            "blogContent": "Spring官網閱讀(二)依賴注入及方法注入",
            "image": "https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
            "createTime": "2020-05-31 11:43:00",
            "transitSimple": null,
            "id": 6
        }
    ]

(3) 使用聯合主鍵查詢單條記錄

//請求方法與URL
GET http://localhost:8088/apiBoot/userBlog/findOne?createUserId=2&title=Spring從入門到精通
//請求響應數據
{
    "status": 200,
    "message": "ok",
    "data": {
        "title": "Spring從入門到精通(一)",
        "createUserId": 2,
        "blogContent": "Spring官網閱讀(一)容器及實例化",
        "image": "https://pic.ibaotu.com/game/title/20200518/5ec24079a85cd.png",
        "createTime": "2020-05-31 11:42:00",
        "transitSimple": null,
        "id": 5
    }
}

3.5 @GeneratedValue

@GeneratedValue爲主鍵生成策略,例如:

public @interface GeneratedValue {
   //ID生成策略
    GenerationType strategy() default GenerationType.AUTO;
   //通過Sequences生成ID,常見的是Oracle數據庫ID的生成規則,需要配合@SequenceGenerator使用
    String generator() default "";
}

GenerationType一共有以下4個值:

public enum GenerationType {
    //通過表產生主鍵,框架有表模擬序列產生主鍵,使用該策略可以使應用更易於數據庫移植
    TABLE,
    //通過序列產生主鍵,通過@SequenceGenerator指定序列名,Mysql不支持這種方式
    SEQUENCE,
    //採用數據庫自增長,一般用於Mysql數據庫
    IDENTITY,
    //JPA自動選擇合適的策略,是默認
    AUTO;
}

3.6 @Basic
@Basic表示屬性是到數據庫表的字段的映射。如果實體的字段上 沒有任何註解,默認即爲@Basic。

public @interface Basic {
    //可選,EAGER(默認)爲立即加載,LAZY爲延遲加載(LAZY主要應用在大字段上面)
    FetchType fetch() default FetchType.EAGER;
    //可選,設置這個字段是否可以爲空,默認爲true
    boolean optional() default true;
}

3.7 @Transient

@Transient表示該屬性並非一個到數據庫表的字段的映射,表示 非持久化屬性;

與@Basic作用相反。JPA映射數據庫的時候忽略它。

3.8 @Column

@Column定義該屬性對應數據庫中的列名

public @interface Column {
    //數據庫表的列名,可選;如果不填寫,默認爲字段名和實體類中的屬性名相同
    String name() default "";
    //是否唯一,默認爲false(可選)
    boolean unique() default false;
    //數據字段是否允許爲null,可選,默認爲true
    boolean nullable() default true;
    //執行insert操作時是否包含此字段,默認爲true,可選
    boolean insertable() default true;
    //執行update操作時是否包含此字段,默認true,可選
    boolean updatable() default true;
    //表示該字段在數據庫中的實際類型
    String columnDefinition() default "";
    //列對應的表名
    String table() default "";
    //字段允許的字符長度,默認爲255
    int length() default 255;
    //精度
    int precision() default 0;
	//小數點位數
    int scale() default 0;

3.9 @Temporal

@Temporal用來設置Date類型的屬性映射到對應精度的字段。

(1)@Temporal(TemporalType.DATE)映射爲日期∥date(只有 日期)

(2)@Temporal(TemporalType.TIME)映射爲日期∥time(只有 時間)

(3)@Temporal(TemporalType.TIMESTAMP)映射爲日期∥date time(日期+時間)

3.10 @Enumerated

@Enumerated很好用,直接映射enum枚舉類型的字段。

(1) 看源碼:

public @interface Enumerated {
    //枚舉映射的類型,默認是ORDINAL(枚舉字段的下標)
    EnumType value() default EnumType.ORDINAL;
}

public enum EnumType {
    //映射枚舉字段的下標
    ORDINAL,
    //映射枚舉的Name
    STRING;
}

(2) 用法:

public enum Gender {
    MAIL("男性"),
    FEMALE("女性")
    ;
    private String value;

    Gender(String value) {
        this.value = value;
    }
}

@Entity
@Table(name="tb_user")
public class User implements Serializable{
    @Enumerated(EnumType.STRING)
    @Column(name="user_gender")
    private Gender gender;
    //....省略其他
}

這時插入兩條數據,數據庫裏面的值是MAIL/FMAIL,而不是“男 性”/“女性”。如果我們用@Enumerated(EnumType.ORDINAL),那麼 這時數據庫裏面的值是0,1。但是實際工作中,不建議用數字下標,

因爲枚舉裏面的屬性值是會不斷新增的,如果新增一個,位置變化了 就慘了。

3.11 @Lob

@Lob 將屬性映射成數據庫支持的大對象類型,支持以下兩種數 據庫類型的字段。

(1)Clob(Character Large Ojects)類型是長字符串類型, java.sql.Clob、Character[]、char[]和String將被映射爲Clob類 型

(2)Blob(Binary Large Objects)類型是字節類型, java.sql.Blob、Byte[]、byte[]和實現了Serializable接口的類型 將被映射爲Blob類型。

(3)Clob、Blob佔用內存空間較大,一般配合 @Basic(fetch=FetchType.LAZY)將其設置爲延遲加載。

小結

本文主要結合源碼和測試用例系統地講解了spring-data-jpa中@Query註解及javax.persistence包下的基本註解及其用法和需要注意的坑,限於文章篇幅,關於聯表查詢的註解及其使用和JpoRepository擴展詳解及高級查詢用法將放在下一遍文章中完成。

推薦閱讀

SpringBoot之路(二)使用用Spring-Data-JPA訪問數據庫進行基本的CRUD操作

參考文檔
張振華著《Spring Data Jpa從入門到精通》第4章和第5章部分

歡迎新讀者掃描下方二維碼關注筆者的微信公衆號

需要源碼的讀者在公衆號中發送消息“bootApi項目源碼”即可獲取該項目源碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章