JPA标记学习

1.@Entity
通过注释@Entity或者(@Entity())表示被标示的类对应数据库中的一张表。
}
@Entity
public class TravelProfile {
...
}
上面的例子告诉O/R映射引擎,类TravelProfile是可以持久化的,同时它对应数据库中的一张表。但是它没有指明对应哪个数据库中的哪张表。
2.元数据映射标记
2.1 @Table
@Table()标记为实体初始化一张表,定义如下:
@Target({TYPE}) @Retention(RUNTIME)
public @interface Table {
String name() default "";
String catalog() default "";
String schema() default "";
UniqueConstraint[] uniqueConstraints() default {};
}
Name:指明表的名字。(可选)
Catalog:表示表的catalog.(可选)
Schema:表示表的schema.(可选)
uniqueConstraints:制定表的唯一约束。(可选)
因为所有的属性都是可选的,也就是说@Table可以在进行映射的时候可以不标明。当不标明的情况下表的名字就是实体的类名。表属于的schema就是所属实体单元集的schema(就是当前连接数据库的用户)。
下面给出的例子中,指明表为CUST,所属的schema为RECORDS:
@Entity
@Table(name="CUST", schema="RECORDS")
public class Customer { ... }

2.2 @UniqueConstraint标记
@UniqueConstraint用来指定表字段的唯一约束,定义如下:
@Target({}) @Retention(RUNTIME)
public @interface UniqueConstraint {
String[] columnNames();
}
columnNames:制定唯一约束的字段。

@Entity
@Table(
name="EMPLOYEE",
uniqueConstraints=
@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})
)
public class Employee { ... }
上面的例子,唯一约束标记指定字段EMP_ID和字段EMP_NAME在表中EMPLOYEE中是唯一的。
2.3@Column标记
@Column标记把实体的属性或域映射到表的字段,当没有在实体的属性或域中使用该标记那数据库的对应表的字段名就是实体的属性名或域名。其定义为:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Column {
String name() default "";
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() default "";
int length() default 255;
int precision() default 0; // decimal precision
int scale() default 0; // decimal scale
}
Name:指定字段名。
Unique:指明该字段是否唯一,默认为false。
Nullable:指明是否可以为空,默认是true。
Insertable:指明该字段在产生SQL INSERT语句中是否产生该字段。
Updatable:指明该字段在产生SQL INSERT语句中是否产生该字段。
columnDefinition:指定产生表的时候,使用它指定该字段一些属性。
Table:当一个实体对应多个表的时候,指定该字段属于哪个表。
Length:制定该字段的长度(只有在字段为字符类型的才有用),默认是255。
Precision: 指明字段的精度(在字段为decimal类型的时候使用),默认是0
Scale:为字段为number型指定标量,默认为0。
下面给出例子:
@Column(name="DESC", nullable=false, length=512)
public String getDescription() { return description; }

@Column(name="DESC",
columnDefinition="CLOB NOT NULL",
table="EMP_DETAIL")
@Lob
public String getDescription() { return description; }

@Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
public BigDecimal getCost() { return cost; }

2.4@JoinColumn标记
@JoinColumn标记用来映射实体之间的关联关系,定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface JoinColumn {
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 "";
}
Name:指定外键字段名,缺省的名字是被引用实体在引用实体内部的属性标量名或域名加上下划线”_”,再加上被引用实体的主键字段名构成。
ReferencedColumnName:被引用表的字段,如果没有那缺省的就是该表的主键。
Unique:指明该字段是否唯一,默认为false。
Nullable:外键是否可以为空,默认是true。
Insertable:指明该字段在产生SQL INSERT语句中是否产生该字段。
Updatable:指明该字段在产生SQL INSERT语句中是否产生该字段。
columnDefinition:指定产生表的时候,使用它指定该字段一些属性。
Table:当一个实体对应多个表的时候,指定该字段属于哪个表。
下面例子的多对一关系中,指明了被引用实体在本实体的外键为ADDR_ID。
@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }

2.5@JoinColumns标记
@JoinColumns标记用在符合外键的时候,这个时候属性name和referencedColumnName必须在@JoinColumn中进行初始化。例如:
@ManyToOne
@JoinColumns({
@JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
@JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
})
public Address getAddress() { return address; }

2.6@Id标记
@Id标记把实体属性或域映射到表的主键。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Id {}
下面例子通过标记@Id初始化实体的主键为id,也可以通过加上标记@Column(name=”PrimaryKey”)自定义表的主键。
@Id
public Long getId() { return id; }

2.7@GeneratedValue标记
提供产生主键的策略,这就意味着它只能在出现标记@Id的情况下使用。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface GeneratedValue {
GenerationType strategy() default AUTO;
String generator() default "";
}

public enum GenerationType { TABLE, SEQUENCE, IDENTITY, AUTO };
策略类型为枚举类型,共有四种类型分别为:TABLE, SEQUENCE, IDENTITY, AUTO。
TABLE:提示持久化引擎实现者,使用数据库的表来产生和维护主键。
SEQUENCE和IDENTITY:分别指定使用当前数据库的序列号和标识字段来产生唯一表识。
AUTO:制定持久化引擎实现者,为不同的数据库选择合适的策略产生唯一标识。

Generator:制定主键产生器,默认有持久化实现者提供。例如:
@Id
@GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
@Column(name="CUST_ID")
public Long getId() { return id; }

@Id
@GeneratedValue(strategy=TABLE, generator="CUST_GEN")
@Column(name="CUST_ID")
Long id;

2.8@IdClass标记
这个标记用来指定一个实体类作为一个另外一个实体的主键。这个时候要求实体的复合主键的每个属性或域必须和复合主键类对应的属性或域是一样的。其定义如下:
@Target({TYPE}) @Retention(RUNTIME)
public @interface IdClass {
Class value();
}
下面例子中,复合主键类为EmployeePK,包含域empName和birthday类型分别为String,Date。
@IdClass(com.jl.hr.EmployeePK.class)
@Entity
public class Employee {
@Id String empName;
@Id Date birthDay;

2.9@Transient标记
标记指示实体的属性或域是非持久化的。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Transient {}

下面的例子说明实体 Employee的域currentUser是非持久化的。
@Entity
public class Employee {
@Id int id;
@Transient User currentUser;
...
}

2.10@Version标记
初始化实体的乐观锁的值,这个标记在大量并发访问的实体中非常有用。如果要对实体使用这个标记那最好的策略是一个实体使用一个@Version标记,同时这个标记对应字段的类型一般为:int,Integer,short,Short,long,Long,Timestamp中的一种。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Version {}

给出相关的例子如下:
@Version
@Column(name="OPTLOCK")
protected int getVersionNum() { return versionNum; }

2.11@Lob标记
此标记初始化实体的属性或域映射成数据库支持的大对象类型。大对象可以是字符也可以是二进制类型。除了字符串和字符类型的默认映射成Blob类型,其它的类型根据实体属性或域的类型来决定数据库大对象的类型。例如:
@Lob
@Column(name="REPORT")
protected String report;

@Lob @Basic(fetch=LAZY)
@Column(name="EMP_PIC", columnDefinition="BLOB NOT NULL")
protected byte[] pic;

2.12@Enumerated标记
用来指定实体持久化属性的为枚举类型,其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Enumerated {
EnumType value() default ORDINAL;
}

public enum EnumType {
ORDINAL,
STRING
}
如果标记没有显性给出或者EnumType没有指定,那枚举类型默认为ORDINAL数字标识。例如:
public enum EmployeeStatus {FULL_TIME, PART_TIME, CONTRACT}
public enum SalaryRate {JUNIOR, SENIOR, MANAGER, EXECUTIVE}
@Entity public class Employee {
...
public EmployeeStatus getStatus() {...}
@Enumerated(STRING)
public SalaryRate getPayScale() {...}
...
}
上面例子中,定义了两个枚举类型EmployeeStatus和SalaryRate。在实体两个属性status类型为EmployeeStatus,而payScale为SalaryRate类型。其中一个显性给出了标记@Enumerated(STRING)来说明枚举类型的值当成字符串使用,而默认的是从1开始的数字来标识的。也可以通过标记@Enumerated(ORDINAL)指示枚举里面类型的值是数字类型的。例如在EmployeeStatus
中的FULL_TIME, PART_TIME, CONTRACT分别代表的数字是1,2,3,4而SalaryRate
中的JUNIOR, SENIOR, MANAGER, EXECUTIVE代表的分别是字符串“JUNIOR”, “SENIOR”, “MANAGER”, “EXECUTIVE”。

2.13@ManyToOne标记
当实体之间的关系是多对一的时候,该标记定义一个单值的字段与其它实体相关联。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
}

public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH};

targetEntity:表示相关联的实体类。
Cascade:级联操作选项,PERSIST, MERGE, REMOVE, REFRESH分别对应增加,更新,删除和查找的联级设置选项。如果选择ALL就使得前面这些联级都生效,也就是cascade=ALL 等同于cascade={PERSIST, MERGE, REMOVE,REFRESH}
Fetch:制定关联实体的加载方式,包括EAGER和LAZY两种方式。当为EAGER选选项的时候,当查询实体的时候会把它相关联的实体实例也加载。当为LAZY的时候加载实体实例的时候与之相关联的实体实例不会加载,默认为EAGER。
Optional:指定关联实体关系是否可以为空,默认是为true。当为false的时候,那当有实体实例的存在总会有与之相关实体实例的存在。
例如:
@ManyToOne(optional=flase)
@JoinColumn(name="CUST_ID", nullable=false, updatable=false)
public Customer getCustomer() { return customer; }

2.14@OneToOne标记
标记定义实体一对一关系的联系,通过一个字段来进行关联。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
String mappedBy() default "";
}
前面四个选项和8.2.13中的意义是一样的。
mappedBy:代表这个属性或域是关系的拥有者,也就是说mappedBy选择应该是在非关系拥有者方才会出现。所谓关系的拥有者就是在表中包含了关系字段的那张表。
现在假设有实体Customer和实体CustomerRecoder它们之间是一对一的关系,同时实体Customer是关系的拥有者。这个时候通过标记@OneToOne来完成关联,在实体Customer相关代码如下:
@OneToOne(optional=false)
@JoinColumn(
name="CUSTREC_ID", unique=true, nullable=false, updatable=false)
public CustomerRecord getCustomerRecord() { return customerRecord; }
在实体CustomerRecord相关代码如下:
@OneToOne(optional=false, mappedBy="customerRecord")
public Customer getCustomer() { return customer; }
因为CustomerRecord是关系的非拥有者所有mappedBy只能在这边出现。


2.15@OneToMany标记
用来标记实体之间的一对多的关系,其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
值得注意的是表示关联实体的集合要使用范形来制定集合内部的关联实体,否则必须要指定targetEntity的实体类型。Fetch类型默认为LAZY而@OneToOne和ManyToOne则默认的为EAGER。
假设现在有实体Customer和Order它们之间的关系是一对多的关系,同时Order是关系的拥有者。
在实体Customer中的代码为:

@OneToMany(cascade=ALL, mappedBy=”customer”)
public Set<Order> getOrders() { return orders; }

在实体Order中的代码为:

@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() { return customer; }

2.16@JoinTable标记
用来映射多对多和单项的一对多关系,当不是用该标记的时候会根据默认的映射原则产生关系连接表。其定义如下:
public @interface JoinTable {
String name() default "";
String catalog() default "";
String schema() default "";
JoinColumn[] joinColumns() default {};
JoinColumn[] inverseJoinColumns() default {};
UniqueConstraint[] uniqueConstraints() default {};
}
Name:指定连接表的名字。
Catalog:指定表所属的catalog。
Schema:指定表所属的schema。
joinColumns:指定关系拥有方作为外键的主键。
inverseJoinColumns:指定关系非拥有方作为外键的主键。
uniqueConstraints:指定表中的唯一约束。
例如:
@JoinTable(
name="CUST_PHONE",
joinColumns=
@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
inverseJoinColumns=
@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
)
上面例子,连接表的名字为CUST_PHONE里面有两个外键,一个来自关系拥有方的主键ID对应外键为CUST_ID;另一个是来自于关系的非拥有方的主键ID对应外键为PHONE_ID。
2.17@ManyToMany标记
标记实体之间的多对多的关系,如果不通过范形来制定集合中的关联实体类型那必须指定相应的关联实体类型。其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
各个属性的意义和标记@OneToMany是一样的,请参照8.2.1.15。
如果关联是双向的两边都可以是关系的拥有方,可以通过标记@JoinTable来制定关系拥有方,请参照2.16。
设有实体Customer和PhoneNumber,则它们的关系映射代码如下:
在实体Customer中为:
@ManyToMany
@JoinTable(name="CUST_PHONES")
public Set<PhoneNumber> getPhones() { return phones; }
在实体PhoneNumber中为:
@ManyToMany(mappedBy="phones")
public Set<Customer> getCustomers() { return customers; }
在实际开发中,对于多对多关系我们经常使用标记@JoinTable来制定关系的拥有方,则对于上面的映射为:
@ManyToMany
@JoinTable(
name="CUST_PHONE",
joinColumns=
@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
inverseJoinColumns=
@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
)
public Set<PhoneNumber> getPhones() { return phones; }

@ManyToMany(mappedBy="phones")
public Set<Customer> getCustomers() { return customers; }

2.18@OrderBy标记
指定批量查询实例实例的时候指定排序的属性或域,其定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OrderBy {
String value() default "";
}
对于使用该标记对应的字段必须是可以比较的,默认的使用的是ASC也可以根据需求改变成DESC。当没有指定value的时候,那默认的就是对实体的主键进行排序,例如:
@Entity public class Course {
...
@ManyToMany
@OrderBy("lastname ASC")
public List<Student> getStudents() {...};
...
}
@Entity public class Student {
...
@ManyToMany(mappedBy="students")
@OrderBy // PK is assumed
public List<Course> getCourses() {...};
...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Data JPA 是什么? Spring Data JPA 是 Spring 框架中的一个模块,它提供了一种方便的方式来访问和操作数据库,同时也简化了开发人员的工作。它基于 JPA 规范,提供了一些常用的 CRUD 操作方法,同时也支持自定义查询和分页查询等功能。 Spring Data JPA 的优点是什么? Spring Data JPA 的优点包括: 1. 简化了数据访问层的开发,提高了开发效率。 2. 提供了一些常用的 CRUD 操作方法,减少了重复的代码编写。 3. 支持自定义查询和分页查询等功能,提高了查询效率。 4. 可以与 Spring 框架无缝集成,方便使用。 5. 支持多种数据库,包括关系型数据库和 NoSQL 数据库等。 6. 提供了一些高级特性,如二级缓存、延迟加载等。 Spring Data JPA 的缺点是什么? Spring Data JPA 的缺点包括: 1. 学习曲线较陡峭,需要掌握 JPA 规范和 Spring 框架的相关知识。 2. 对于复杂的查询,需要编写自定义查询语句,增加了开发难度。 3. 对于大规模数据的查询和操作,可能会出现性能问题。 4. 对于一些特殊的需求,可能需要使用原生 SQL 或其他 ORM 框架来实现。 Spring Data JPA 和 Hibernate 有什么区别? Spring Data JPA 是基于 JPA 规范的,而 Hibernate 是一个 ORM 框架,它实现了 JPA 规范。因此,Spring Data JPA 和 Hibernate 之间的区别主要在以下几个方面: 1. Spring Data JPA 是一个数据访问层框架,而 Hibernate 是一个 ORM 框架。 2. Spring Data JPA 提供了一些常用的 CRUD 操作方法,而 Hibernate 更加灵活,可以编写任意复杂的查询语句。 3. Spring Data JPA 可以与 Spring 框架无缝集成,而 Hibernate 可以与任何 Java 应用程序集成。 4. Spring Data JPA 支持多种数据库,包括关系型数据库和 NoSQL 数据库等,而 Hibernate 主要支持关系型数据库。 5. Spring Data JPA 提供了一些高级特性,如二级缓存、延迟加载等,而 Hibernate 也提供了类似的特性。 如何使用 Spring Data JPA? 使用 Spring Data JPA 的步骤如下: 1. 添加依赖:在项目的 pom.xml 文件中添加 Spring Data JPA 的依赖。 2. 配置数据源:在 Spring 的配置文件中配置数据源。 3. 定义实体类:定义与数据库表对应的实体类,并使用 JPA 注解进行映射。 4. 定义 DAO 接口:定义一个继承 JpaRepository 接口的 DAO 接口。 5. 编写业务逻辑:在 Service 层中编写业务逻辑,调用 DAO 接口中的方法进行数据操作。 6. 运行程序:启动应用程序,测试数据访问和操作是否正常。 如何进行分页查询? 使用 Spring Data JPA 进行分页查询的步骤如下: 1. 在 DAO 接口中定义一个继承 PagingAndSortingRepository 接口的方法。 2. 在 Service 层中调用 DAO 接口中的分页查询方法,并指定分页参数。 3. 在控制器中接收分页参数,并将查询结果传递给前端页面。 4. 在前端页面中显示分页信息和查询结果。 如何进行自定义查询? 使用 Spring Data JPA 进行自定义查询的步骤如下: 1. 在 DAO 接口中定义一个自定义查询方法,并使用 @Query 注解指定查询语句。 2. 在 Service 层中调用 DAO 接口中的自定义查询方法。 3. 在控制器中接收查询结果,并将结果传递给前端页面。 4. 在前端页面中显示查询结果。 如何进行事务管理? 使用 Spring Data JPA 进行事务管理的步骤如下: 1. 在 Spring 的配置文件中配置事务管理器。 2. 在 Service 层中使用 @Transactional 注解标记需要进行事务管理的方法。 3. 在控制器中调用 Service 层中的方法。 4. 如果方法执行成功,则事务会自动提交,否则事务会自动回滚。 如何进行多表查询? 使用 Spring Data JPA 进行多表查询的步骤如下: 1. 在 DAO 接口中定义一个自定义查询方法,并使用 @Query 注解指定查询语句。 2. 在查询语句中使用 JOIN 关键字连接多个表。 3. 在 Service 层中调用 DAO 接口中的自定义查询方法。 4. 在控制器中接收查询结果,并将结果传递给前端页面。 5. 在前端页面中显示查询结果。 如何进行级联操作? 使用 Spring Data JPA 进行级联操作的步骤如下: 1. 在实体类中使用 @OneToMany 或 @ManyToOne 注解定义关联关系。 2. 在 Service 层中编写业务逻辑,调用 DAO 接口中的方法进行级联操作。 3. 在控制器中接收操作结果,并将结果传递给前端页面。 4. 在前端页面中显示操作结果。 如何进行缓存管理? 使用 Spring Data JPA 进行缓存管理的步骤如下: 1. 在 Spring 的配置文件中配置缓存管理器。 2. 在实体类中使用 @Cacheable 或 @CacheEvict 注解指定缓存策略。 3. 在 Service 层中编写业务逻辑,调用 DAO 接口中的方法进行数据操作。 4. 在控制器中接收操作结果,并将结果传递给前端页面。 5. 在前端页面中显示操作结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值