组合主键
主键最常见的是单字段主键,组合主键使用两个及以上的字段作为主键,常用于多个字段能唯一标示一条记录的表。比如,股票数据表,股票代码、日期和收盘价作为主键。每支股票,在一个特定日期,只能有一个收盘价。
数据库管理系统使用MySQL,创建一个具有组合主键的表Person。
CREATE TABLE PERSON ( name VARCHAR(255) NOT NULL, age BIGINT UNSIGNED NOT NULL, adress VARCHAR(255) , PRIMARY KEY (name, age) ) ENGINE = InnoDB;
JPA映射之@IdClass
定义工具类
package com.gxz.entities; import java.io.Serializable; public class PersonCompositeId implements Serializable { private String name; private long age; public String getName() { return name; } public void setName(String name) { this.name = name; } public long getAge() { return age; } public void setAge(long age) { this.age = age; } }
该工具类的属性必须和实体类的@Id属性完全匹配。包括数量、名字,不能有额外的属性。
定义实体类
package com.gxz.entities; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; @Entity @Table @IdClass(PersonCompositeId.class) public class Person { private String name; private long age; private String adress; @Id public String getName() { return name; } public void setName(String name) { this.name = name; } @Id public long getAge() { return age; } public void setAge(long age) { this.age = age; } public String getAdress() { return adress; } public void setAdress(String adress) { this.adress = adress; } }
该实体类有两个属性标示为@Id,表示主键为组合主键,主键属性为name、age。相应地,工具类PersonCompositeId必须有两个属性,分别为name、age。注意,此处指的是工具类必须有getName、setName、getAge、setAge,而不是指必须有字段name、age,注意区分属性和字段的区别。@IdClass(PersonCompositeId.class):表示使用工具类PersonCompositeId定义组合主键。另外,工具类PersonCompositeId必须实现序列化Serializable,否则,报出如下异常。
[PersistenceUnit: EntityMappings] Unable to build Hibernate SessionFactory Composite-id class must implement Serializable: com.gxz.entities.PersonCompositeId Composite-id class must implement Serializable: com.gxz.entities.PersonCompositeId
持久化
Person person = new Person(); person.setName("李四"); person.setAge(40); person.setAdress("广州市"); manager.persist(person);
根据id查找实体
PersonCompositeId personCompositeId = new PersonCompositeId(); personCompositeId.setName("张三"); personCompositeId.setAge(50); Person person = manager.find(Person.class, personCompositeId); if (person != null) { System.out.println("name:" + person.getName() + " age:" + person.getAge()); }
JPA映射之@EmbeddedId
定义工具类
package com.gxz.entities; import java.io.Serializable; import javax.persistence.Embeddable; @Embeddable public class PersonCompositeId implements Serializable { private String name; private long age; public String getName() { return name; } public void setName(String name) { this.name = name; } public long getAge() { return age; } public void setAge(long age) { this.age = age; } }
@Embeddable:表示该工具类用于组合主键,属性就是组合主键的属性。
定义实体类
package com.gxz.entities; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table public class Person { private PersonCompositeId personCompositeId; @EmbeddedId public PersonCompositeId getPersonCompositeId() { return personCompositeId; } public void setPersonCompositeId(PersonCompositeId personCompositeId) { this.personCompositeId = personCompositeId; } private String adress; public String getAdress() { return adress; } public void setAdress(String adress) { this.adress = adress; } }
@EmbeddedId:表示该属性是组合主键,类型是组合主键工具类。
持久化
PersonCompositeId personCompositeId = new PersonCompositeId(); personCompositeId.setName("搜噶"); personCompositeId.setAge(100); person.setPersonCompositeId(personCompositeId); person.setAdress("广州市"); manager.persist(person); transaction.commit();
两种映射方式的比较
第一种方式,工具类和实体类有一模一样的属性,属于冗余,第二种方式则没有没有冗余,显得更加科学。因此,实际工作中,第二种方式更加常用。
时间: 2024-10-25 23:39:31