前面章节已经介绍了 @Id 注解,该注解定义实体类中某个属性为数据库的主键,一个实体里面必须有一个主键。本章节将介绍 @IdClass 注解,该注解用来为某个实体指定复合主键,复合主键存放在一个单独的类当中。
符合主键类需要要满足以下要求:
必须实现 Serializable 接口;
必须有默认的 public 无参数的构造方法;
必须覆盖 equals 和 hashCode 方法。equals 方法用于判断两个对象是否相同,EntityManger 通过 find 方法来查找 Entity 时是根据 equals 的返回值来判断的。hashCode 方法返回当前对象的哈希码,生成的 hashCode 相同的概率越小越好,算法可以进行优化。
(1)假设我们拥有一张 users2 表,该表使用 “name” + “phone” 作为复合主键。SQL 脚本如下:
CREATE TABLE `users2` ( `name` varchar(100) NOT NULL, `phone` varchar(15) NOT NULL, `email` varchar(100) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, PRIMARY KEY (`name`,`phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(2)为上面的 users2 表的复合主键 “name” + “phone” 创建复合主键 User11Key.java 类,代码如下:
import lombok.Data;
import java.io.Serializable;
@Data
public class User11Key implements Serializable {
private String name;
private String phone;
public User11Key() {}
public User11Key(String name, String phone) {
this.name = name;
this.phone = phone;
}
}(3)为 users2 表创建一个实体类,在实体类上面使用 @IdClass 注解指定复合主键。同时,需要在 name 和 phone 字段上面使用 @Id 注解标记为主键。代码如下:
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "users2")
@IdClass(value = User11Key.class)
public class User11 {
// 指定为主键
@Id
@Column(nullable = false)
private String name;
// 指定为主键
@Id
@Column(nullable = false)
private String phone;
@Column
private String email;
@Column
private String address;
}(4)客户端代码,使用 EntityManager 的实例根据复合主键查询 users 表中的数据。代码如下:
import com.alibaba.fastjson.JSONObject;
import com.huangx.openjpa.annotation.entity.User11;
import com.huangx.openjpa.annotation.entity.User11Key;
import javax.jws.soap.SOAPBinding;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.List;
public class OpenJpaDemo11 {
/** 持久化单元名称 */
private static final String NAME = "openJPA";
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 根据主键查询数据
User11 user = em.find(User11.class, new User11Key("张三", "15188994534"));
System.out.println(JSONObject.toJSONString(user));
em.getTransaction().commit();
em.close();
emf.close();
System.out.println("finished.");
}
}