Spring Boot 学习研究笔记(九) - Spring Data JPA常用注解(2)

简介: Spring Boot 学习研究笔记(九) - Spring Data JPA常用注解

8、@MapKey

在一对多,多对多关系中,我们可以用Map来保存集合对象。默认用主键值做key,如果使用复合主键,则用id class的实例做key,如果指定了name属性,就用指定的field的值做key。

元数据属性说明: name: 用来做key的field名字

下面的代码说明Person和Book之间是一对多关系。Person的books字段是Map类型,用Book的isbn字段的值作为Map的key。

@Table(name = "PERSON")
    public class Person {
 @OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person")
 @MapKey(name = "isbn")
 private Map books = new HashMap();
    }

 

9、@OrderBy

在一对多,多对多关系中,有时我们希望从数据库加载出来的集合对象是按一定方式排序的,这可以通过OrderBy来实现,默认是按对象的主键升序排列。

元数据属性说明: value: 字符串类型,指定排序方式。

格式为"fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],…",排序类型可以不指定,默认是ASC。

下面的代码说明Person和Book之间是一对多关系。集合books按照Book的isbn升序,name降序排列。

@Table(name = "MAPKEY_PERSON")
    public class Person {
 @OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person")
 @OrderBy(name = "isbn ASC, name DESC")
 private List books = new ArrayList();
    }

 

10、@PrimaryKeyJoinColumn

在三种情况下会用到PrimaryKeyJoinColumn。

  • 继承
  • entity class映射到一个或多个从表。从表根据主表的主键列(列名为referencedColumnName值的列),建立一个类型一样的主键列,列名由name属性定义。
  • one2one关系,关系维护端的主键作为外键指向关系被维护端的主键,不再新建一个外键列。

元数据属性说明

  • name:列名
  • referencedColumnName:该列引用列的列名
  • columnDefinition: 定义建表时创建此列的DDL

下面的代码说明Customer映射到两个表,主表CUSTOMER,从表CUST_DETAIL,从表需要建立主键列CUST_ID,该列和主表的主键列id除了列名不同,其他定义一样。

@Entity
    @Table(name="CUSTOMER")
 @SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID",referencedColumnName="id"))
 public class Customer { 
  @Id(generate = GeneratorType.AUTO)
   public Integer getId() {
    return id;
   }
 }

下面的代码说明Employee和EmployeeInfo是一对一关系,Employee的主键列id作为外键指向EmployeeInfo的主键列INFO_ID。

 

@Table(name = "Employee")
    public class Employee {
 @OneToOne
 @PrimaryKeyJoinColumn(name = "id", referencedColumnName="INFO_ID")
 EmployeeInfo info;
 }

11、@PrimaryKeyJoinColumns

如果entity class使用了复合主键,指定单个PrimaryKeyJoinColumn不能满足要求时,可以用PrimaryKeyJoinColumns来定义多个PrimaryKeyJoinColumn。

元数据属性说明: value: 一个PrimaryKeyJoinColumn数组,包含所有PrimaryKeyJoinColumn。

 

下面的代码说明了Employee和EmployeeInfo是一对一关系。他们都使用复合主键,建表时需要在Employee表建立一个外键,从Employee的主键列id,name指向EmployeeInfo的主键列INFO_ID和INFO_NAME.

@Entity
   @IdClass(EmpPK.class)
   @Table(name = "EMPLOYEE")
   public class Employee {
 private int id;
 private String name;
 private String address;
 @OneToOne(cascade = CascadeType.ALL)
 @PrimaryKeyJoinColumns({
 @PrimaryKeyJoinColumn(name="id", referencedColumnName="INFO_ID"),
 @PrimaryKeyJoinColumn(name="name" , referencedColumnName="INFO_NAME")})
 EmployeeInfo info;
    }
    @Entity
    @IdClass(EmpPK.class)
    @Table(name = "EMPLOYEE_INFO")
    public class EmployeeInfo {
 @Id
 @Column(name = "INFO_ID")
 private int id;
 @Id
 @Column(name = "INFO_NAME")
 private String name;
 }

12、@Transient

@Transient表示该属性并不是一个到数据库表的字段的映射,指定的这些属性不会被持久化,ORM框架将忽略该属性。 如果一个属性并非数据库表的字段映射。就务必将其标示为@Transient。否则,ORM框架默认其注解为@Basic

 @Transient

  private String name;

 

13、@SecondaryTable

一个entity class可以映射到多表,SecondaryTable用来定义单个从表的名字,主键名字等属性。

元数据属性说明:

name:表名

catalog:对应关系数据库中的catalog

schema:对应关系数据库中的 schema

pkJoin: 定义一个PrimaryKeyJoinColumn数组,指定从表的主键列

UniqueConstraints: 定义一个UniqueConstraint数组,指定需要建唯一约束的列。

下面的代码说明Customer类映射到两个表,主表名是CUSTOMER,从表名是CUST_DETAIL,从表的主键列和主表的主键列类型相同,列名为CUST_ID。

@Entity
@Table(name="CUSTOMER")
@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
 public class Customer { ... }

14、@SecondaryTables

当一个entity class映射到一个主表和多个从表时,用SecondaryTables来定义各个从表的属性。

元数据属性说明: value: 定义一个SecondaryTable数组,指定每个从表的属性。

@Table(name = "CUSTOMER")
@SecondaryTables( value = {
@SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }),
@SecondaryTable(name = "CUST_ADDRESS", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }) })
public class Customer {}

 

15、@Version

Version指定实体类在事务中的version属性。在实体类重新由EntityManager管理并且加入到事务中时,保证完整性。每一个类只能有一个属性被指定为version,version属性应该映射到实体类的主表上。

   @Version

   @Column("OPTLOCK")

   protected int getVersionNum() { return versionNum; }


16、@Lob

Lob指定一个属性作为数据库支持的大对象类型在数据库中存储。使用LobType这个枚举来定义Lob是二进制类型还是字符类型。

 

LobType枚举类型说明:

  • BLOB 二进制大对象,Byte[]或者Serializable的类型可以指定为BLOB。
  • CLOB 字符型大对象,char[]、Character[]或String类型可以指定为CLOB。

 

元数据属性说明:

  • fetch: 定义这个字段是lazy loaded还是eagerly fetched。数据类型是FetchType枚举,默认为LAZY,即lazy loaded.
  • type: 定义这个字段在数据库中的JDBC数据类型。数据类型是LobType枚举,默认为BLOB。

下面的代码定义了一个BLOB类型的属性和一个CLOB类型的属性。

 

@Lob
    @Column(name="PHOTO" columnDefinition="BLOB NOT NULL")
    protected JPEGImage picture;
    @Lob(fetch=EAGER, type=CLOB)
    @Column(name="REPORT")
    protected String report;

17、@JoinTable

JoinTable在many-to-many关系的所有者一边定义。如果没有定义JoinTable,使用JoinTable的默认值。

元数据属性说明:

  • table:这个join table的Table定义。
  • joinColumns:定义指向所有者主表的外键列,数据类型是JoinColumn数组。
  • inverseJoinColumns:定义指向非所有者主表的外键列,数据类型是JoinColumn数组。

下面的代码定义了一个连接表CUST和PHONE的join table。join table的表名是CUST_PHONE,包含两个外键,一个外键是CUST_ID,指向表CUST的主键ID,另一个外键是PHONE_ID,指向表PHONE的主键ID。

 

@JoinTable(
    table=@Table(name=CUST_PHONE),
    joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
    inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
    )

18、@DiscriminatorColumn

DiscriminatorColumn定义在使用SINGLE_TABLE或JOINED继承策略的表中区别不继承层次的列。

元数据属性说明:

  • name:column的名字。默认值为TYPE。
  • columnDefinition:生成DDL的sql片断。
  • length:String类型的column的长度,其他类型使用默认值10。

下面的代码定义了一个列名为DISC,长度为20的String类型的区别列。

 

@Entity
    @Table(name="CUST")
    @Inheritance(strategy=SINGLE_TABLE,
        discriminatorType=STRING,
       discriminatorValue="CUSTOMER")
    @DiscriminatorColumn(name="DISC", length=20)
    public class Customer { ... }

19、@OneToOne、@JoinColumn

@OneToOne注释只能确定实体与实体的关系是一对一的关系,不能指定数据库表中的保存的关联字段。所以此时要结合@JoinColumn标记来指定保存实体关系的配置。

@JoinColumn与@Column注释类似,它的定义如下代码所示。

@Target({METHOD, FIELD})
 @Retention(RUNTIME) 
String name() default ""; 
String referencedColumnName() default ""; 
boolean unique() default false; 
boolean nullable() default true; 
boolean insertable() default true; 
boolean updatable() default true; 
String columnDefinition() default ""; 
String table() default ""; 
}


在使用@JoinColumn时,应注意以下几个问题:

(1)、 @JoinColumn与@Column标记一样,是用于注释表中的字段的。它的属性与@Column属性有很多相同之处

(2)、@JoinColumn与@Column相区别的是:@JoinColumn注释的是保存表与表之间关系的字段,它要标注在实体属性上。而@Column标注的是表中不包含表关系的字段。

(3)、与@Column标记一样,name属性是用来标识表中所对应的字段的名称。

例如customer表中存在字段addr_id,标识的代码如下所示。

@OneToOne 
@JoinColumn(name = "addr_id") 
public AddressEO getAddress() {
   return address; 
}

若此时,不设置name的值,则在默认情况下,name的取值遵循以下规则: name=关联表的名称+“_”+ 关联表主键的字段名

例如,CustomerEO实体中,如果不指定name的值,默认将对应name=address_id;

因为@JoinColumn注释在实体 AddressEO属性上,实体AddressEO对应的表名为“address”;表address的主键是“id”,所以此时对应的默认的字段名称为 “address_id”。

注意:

此规则只适用于与@OneToOne标记同时使用时。若与@ManyToOne或@ManyToMany标记同时使用时,将遵循其他的规则。

默认情况下,关联的实体的主键一般是用来做外键的。但如果此时不想主键作为外键,则需要设置referencedColumnName属性。

例如,将address表中增加一个字段“ref_id”,address表的建表SQL变为以下所示。

CREATE TABLE address (
    id int(20) NOT NULL auto_increment, 
ref_id int int(20) NOT NULL, 
province varchar(50) ,   
city varchar(50) , 
postcode varchar(50) , 
detail varchar(50) , 
PRIMARY KEY (id) 
) 
此时,通过customer表中的“address_id”字段关联的是address表中的“ref_id”,而“ref_id”并不是address表中的主键,则实体中标注如代码下所示。
@OneToOne 
@JoinColumn(name = "address_id",referencedColumnName="ref_id") 
public AddressEO getAddress() {
         return address;     
}

 

20、Hibernate验证注解

注解 适用类型 说明 示例
@Pattern String 通过正则表达式来验证字符串 @attern(regex=”[a-z]{6}”)
@Length String 验证字符串的长度 @length(min=3,max=20)
@Email String 验证一个Email地址是否有效 @email
@Range Long 验证一个整型是否在有效的范围内 @Range(min=0,max=100)
@Min Long 验证一个整型必须不小于指定值 @Min(value=10)
@Max Long 验证一个整型必须不大于指定值 @Max(value=20)
@Size 集合或数组 集合或数组的大小是否在指定范围内 @Size(min=1,max=255)

以上每个注解都可能性有一个message属性,用于在验证失败后向用户返回的消息。

相关文章
|
9月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
784 2
|
10月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
1533 128
|
10月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
659 12
存储 JSON Java
974 0
|
10月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
551 0
探索Spring Boot的@Conditional注解的上下文配置
|
SQL Java 编译器
深入理解 Spring Data JPA 的导入与使用:以 UserRepository为例
本文深入解析了 Spring Data JPA 中 `UserRepository` 的导入与使用。通过示例代码,详细说明了为何需要导入 `User` 实体类、`JpaRepository` 接口及 `@Repository` 注解。这些导入语句分别用于定义操作实体、提供数据库交互方法和标识数据访问组件。文章还探讨了未导入时的编译问题,并展示了实际应用场景,如用户保存、查询与删除操作。合理使用导入语句,可让代码更简洁高效,充分发挥 Spring Data JPA 的优势。
824 0
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
【Java笔记+踩坑】Spring Data JPA
|
Java Spring 数据库
怎样动动手指就能实现数据操作?Spring Data JPA背后的魔法揭秘
【8月更文挑战第31天】在Java开发中,数据库交互至关重要。传统的JDBC操作繁琐且难维护,而Spring Data JPA作为集成JPA的数据访问层解决方案,提供了CRUD等通用操作接口,显著减少代码量。通过继承`JpaRepository`,开发者能轻松实现数据的增删改查,甚至复杂查询和分页也不再困难。本文将通过示例详细介绍如何利用Spring Data JPA简化数据访问层的开发,提升代码质量和可维护性。
289 0
|
存储 Java 数据库
|
存储 Java API

热门文章

最新文章