使用JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId问题
作者:罗罗诺亚F 发布时间:2022-07-07 18:35:41
JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId
1、自动主键
默认情况下,主键是一个连续的64位数字(long),它由ObjectDB自动为存储在数据库中的每个新实体对象自动设置。
数据库中的第一个实体对象的主键是1,第二个实体对象的主键是2等等。
当从数据库中删除实体对象时,主键值不会被回收。
一个实体的主键值可以通过声明一个主键字段来访问:
@Entity
public class Project {
@Id @GeneratedValue long id; // still set automatically
}
@id
标注将字段标记为一个主键字段。当定义主键字段时,主键值将被ObjectDB自动注入到该字段中。@generatedvalue
注释指定主键是由ObjectDB自动分配的
2、应用设置主键
如果一个实体有一个没有@generatedvalue标记的主键字段,则不会生成自动主键值,并且应用程序负责通过初始化主键字段来设置主键。这必须在持久化实体对象的任何尝试之前完成。
@Entity
public class Project {
@Id long id; // must be initialized by the application
}
应用程序设置的主键字段可以有以下类型:
● 原始类型: boolean, byte, short, char, int, long, float, double.
● java.lang包中的包装类型:Byte, Short, Character, Integer, Long, Float, Double.
● java.math.BigInteger, java.math.BigDecimal.
● java.lang.String.
● java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp.
● 枚举类型
● 引用一个实体对象
3、复合主键
复合主键由多个主键字段组成。每个主键字段必须是上面列出的支持类型之一。
例如,以下项目实体类的主键由两个字段组成:
@Entity @IdClass(ProjectId.class)
public class Project {
@Id int departmentId;
@Id long projectId;
}
当一个实体有多个主键字段时,JPA需要定义一个特殊的ID类,该类是使用@idclass注释附加到实体类的。ID类反映了主键字段,它的对象可以表示主键值:
Class ProjectId {
int departmentId;
long projectId;
}
ObjectDB不强制定义ID类。但是,如果实体对象必须按照检索实体部分中所示的主键来检索实体对象,那么就需要ID类。
4、嵌入式主键
表示复合主键的另一种方法是使用可嵌入的类:
@Entity
public class Project {
@EmbeddedId ProjectId id;
}
@Embeddable
Class ProjectId {
int departmentId;
long projectId;
}
主键字段是在可嵌入类中定义的。
该实体包含一个单独的主键字段,该字段用@EmbeddedId 注释,并包含一个可嵌入类的实例。
当使用这个表单时,没有定义一个单独的ID类,因为可嵌入的类本身可以表示完整的主键值。
@EmbeddedId和@IdClass的区别
@idClass
使复合主键类成为非嵌入类,使用 @IdClass 批注为实体指定一个复合主键类(通常由两个或更多基元类型或 JDK 对象类型组成)。从原有数据库映射时(此时数据库键由多列组成),通常将出现复合主键。
复合主键类具有下列特征:
它是一个普通的旧式 Java 对象 (POJO) 类。
它必须为 public,并且必须有一个 public 无参数构造函数。
如果使用基于属性的访问,则主键类的属性必须为 public 或 protected。
它必须是可序列化的。
它必须定义 equals 和 hashCode 方法。
这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
它的字段或属性的类型和名称必须与使用 @Id 进行批注的实体主键字段或属性的类型和名称相对应。
package com.model;
import java.io.Serializable;
public class SysUserRoleId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 2606793267849167078L;
private Long userId;
private Long roleId;
@Override
public int hashCode(){
int result = 1;
result = userId.hashCode()+roleId.hashCode();
return result;
}
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return true;
}
if(getClass() != obj.getClass()){
return false;
}
final SysUserRoleId other = (SysUserRoleId) obj;
if(other.getUserId().equals(this.userId) && other.getRoleId().equals(this.roleId)){
return true;
}
return false;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
}
package com.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
@Entity
@Table(name="SYS_USER_ROLE")
@IdClass(SysUserRoleId.class)
public class SysUserRole {
private Long userId;
private Long roleId;
public SysUserRole(){
}
public SysUserRole(Long userId,Long roleId){
this.userId = userId;
this.roleId = roleId;
}
@Id
@Column(name="user_id")
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
@Id
@Column(name="role_id")
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
}
@EmbeddedId
使复合主键类成为由实体拥有的嵌入类
使用 @EmbeddedId 批注指定一个由实体拥有的可嵌入复合主键类(通常由两个或更多基元类型或 JDK 对象类型组成)。从原有数据库映射时(此时数据库键由多列组成),通常将出现复合主键。
复合主键类具有下列特征:
它是一个普通的旧式 Java 对象 (POJO) 类。
它必须为 public,并且必须有一个 public 无参数构造函数。
如果使用基于属性的访问,则主键类的属性必须为 public 或 protected。
它必须是可序列化的。
它必须定义 equals 和 hashCode 方法。
这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
package com.model;
import java.io.Serializable;
import javax.persistence.Column;
@SuppressWarnings("serial")
public class SysOrganizationRolePKId implements Serializable{
private Long organizationId;
private Long roleId;
@Column(name="organization_id")
public Long getOrganizationId() {
return organizationId;
}
public void setOrganizationId(Long organizationId) {
this.organizationId = organizationId;
}
@Column(name="role_id")
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
}
package com.model;
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@SuppressWarnings("serial")
@Table(name="SYS_ORGANIZATION_ROLE")
public class SysOrganizationRole implements Serializable{
private SysOrganizationRolePKId sysOrganizationRolePKId;
@EmbeddedId
public SysOrganizationRolePKId getSysOrganizationRolePKId() {
return sysOrganizationRolePKId;
}
public void setSysOrganizationRolePKId(
SysOrganizationRolePKId sysOrganizationRolePKId) {
this.sysOrganizationRolePKId = sysOrganizationRolePKId;
}
}
来源:https://hamburger.blog.csdn.net/article/details/78319021


猜你喜欢
- 这篇文章主要介绍了Spring 自动装配的二义性实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 本文实例讲述了C#实现抓取和分析网页类。分享给大家供大家参考。具体分析如下:这里介绍了抓取和分析网页的类。其主要功能有:1、提取网页的纯文本
- 一、获取安装包信息/** * 获取apk包的信息:版本号,名称,图标等 * @param absPath apk包的绝对路径 * @para
- log4j的rootLogger及其他坑爹地方这里用的是org.apache.log4j.Loggerlog4j.rootLogger=er
- 实际需求<if test="computationRule == '1'"> F
- 本文记录一下,我从AndroidStudio 2.3.3升级到3.0,再升级到3.0.1一路上遇到的输入法之坑以及解决方案。前些天把Andr
- 一、实验:继承1、概念Maven工程之间,A 工程继承 B 工程B 工程:父工程A 工程:子工程本质上是 A 工程的 pom.xml 中的配
- 在实际项目的开发过程中,所涉及的EXCEL往往会比较复杂,并且列中还会带有一些计算公式,这就给读取带来了很大的困难,曾经尝试过一些免费的第三
- 组件在容器(比如Jframe)中的位置和大小是由布局管理器来决定的。所有的容器都会使用一个布局管理器,通过它来自动进行组件的布局管理。种类j
- Redis中opsForValue()方法的使用1、set(K key, V value)新增一个字符串类型的值,key是键,value是值
- IDEA快速搭建spring boot项目1.创建项目老规矩,点击Create New Project2.编写控制器在com.demo.sp
- SpringBoot监控Actuator,关闭redis监测方法当我们导入了spring-boot-starter-actuator这个依赖
- C++ boost::asio编程-异步TCP大家好,我是异步方式和同步方式不同,我从来不花时间去等那些龟速的IO操作,我只是向系统说一声要
- 在上一篇实现了简单的画板功能, 这篇实现橡皮擦功能,首先分析一下应该如何实现,在Andriod有个图像混合(Xfermode)概念,利用这个
- 本文实例讲述了Android中ProgressBar用法。分享给大家供大家参考,具体如下:在android中会经常用到ProgressBar
- 1. F1弹出帮助文档先找个后缀是pdf、docx等格式的的帮助文档,将它放在项目的helpDoc下。设置其“复制到输出
- 目录对zygote的理解作用启动流程启动入口脚本讲解启动过程App_main::mainAndroidRuntime::start对zygo
- 1.使用API设置主题如下所示,在Activity中使用setThemesetTheme(R.style.MyTheme1);2.调用API
- Android有三个基础组件Activity,Service和BroadcastReceiver,他们都是依赖Intent来启动。本文介绍的
- 前言:函数式编程是一种编程范式,其中程序是通过应用和组合函数来构造的。它是一种声明式编程范式,其中函数定义是表达式树,每个表达式树返回一个值