关于Java中带@EmbeddedId注解的Person实体类及PersonIdentity类的问询
嘿,我来帮你把这个Person实体类和对应的PersonIdentity嵌入式主键类的细节梳理清楚,包括注解解析、代码示例和常见坑点👇
1. 解析现有Person实体类
先把你的原代码贴出来,方便对照讲解:
@Data @Entity @NoArgsConstructor @XmlRootElement(name="Person") @XmlAccessorType(XmlAccessType.FIELD) public class Person implements Serializable { @EmbeddedId private PersonIdentity persondentity; // 注意:这里变量名大概率是笔误,建议改成`personIdentity`更规范 private String name; private Boolean active; private Boolean closed; @XmlJavaTypeAdapter(DateAdapter.class) @XmlAttribute(name = "DateBirth") private Date birth; @XmlAttribute(name = "PersonName") private String personaName; }
关键注解&字段拆解
JPA核心注解:
@Entity:标记这是一个JPA实体类,对应数据库中的一张表@EmbeddedId:指定PersonIdentity是嵌入式复合主键,意味着这个实体的主键由PersonIdentity中的多个字段共同组成@NoArgsConstructor:Lombok注解,自动生成无参构造器——这是JPA强制要求的,否则实体无法被持久化@Data:Lombok懒人神器,自动生成getter、setter、equals、hashCode、toString等方法,省去大量重复代码
JAXB注解(用于XML序列化/反序列化):
@XmlRootElement(name="Person"):指定XML序列化后的根元素名称为<Person>@XmlAccessorType(XmlAccessType.FIELD):告诉JAXB直接操作类的字段,而不是通过getter/setter方法,简化配置@XmlAttribute(name = "DateBirth"):把birth字段映射为XML元素的属性(而非子元素),属性名是DateBirth@XmlJavaTypeAdapter(DateAdapter.class):自定义日期类型的XML适配器,解决java.util.Date和XML标准日期格式的转换问题(比如把Date转成yyyy-MM-dd格式的字符串)@XmlAttribute(name = "PersonName"):把personaName字段映射为XML元素的属性PersonName
字段说明:
persondentity:复合主键的载体,建议修正拼写为personIdentity避免后续混淆name/active/closed:普通业务字段,对应数据库表中的列birth:日期类型字段,通过适配器处理XML转换逻辑personaName:额外的名称字段,专门映射为XML属性
2. 编写对应的PersonIdentity嵌入式主键类
因为用了@EmbeddedId,PersonIdentity必须满足JPA嵌入式主键的硬性要求,下面是标准实现示例:
@Data @Embeddable public class PersonIdentity implements Serializable { // 这里的字段完全根据业务需求定义,只要能唯一标识一个Person即可,比如: private Long userId; private String countryCode; // 如果你不想用Lombok的@Data,就手动实现以下内容: // public PersonIdentity() {} // 必须有无参构造器 // // @Override // public boolean equals(Object o) { // if (this == o) return true; // if (o == null || getClass() != o.getClass()) return false; // PersonIdentity that = (PersonIdentity) o; // return Objects.equals(userId, that.userId) && Objects.equals(countryCode, that.countryCode); // } // // @Override // public int hashCode() { // return Objects.hash(userId, countryCode); // } }
这个类的核心要求
@Embeddable:标记该类可以被嵌入到实体类中作为主键使用- 必须实现
Serializable:JPA在持久化、传输实体时需要序列化主键 - 必须正确实现
equals()和hashCode():JPA依赖这两个方法判断实体的唯一性,一定要基于主键字段实现 - 字段选择:完全贴合业务场景,比如可以是「身份证号+手机号」「用户ID+租户ID」等组合
3. 常见问题&注意事项
- 变量名笔误修正:原代码中的
persondentity建议改成personIdentity,避免后续开发中出现拼写错误的bug - DateAdapter的实现示例:如果还没写这个适配器,参考下面的基础实现:
public class DateAdapter extends XmlAdapter<String, Date> { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date unmarshal(String v) throws Exception { return DATE_FORMAT.parse(v); // 把XML字符串转成Date } @Override public String marshal(Date v) throws Exception { return DATE_FORMAT.format(v); // 把Date转成XML标准字符串 } }
- 复合主键的查询方式:用JPA查询时,需要先构造
PersonIdentity实例作为参数:
PersonIdentity id = new PersonIdentity(); id.setUserId(1L); id.setCountryCode("CN"); Person person = entityManager.find(Person.class, id);
内容的提问来源于stack exchange,提问作者jre
相关产品推荐
相关产品推荐

