Hibernate实体关联关系映射
双向一对一关联
@Entity(name = "address")
@Table(name = "t_address")
public class Address implements Serializable {
private static final long serialVersionUID = 2390103918524410815L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "addressID")
@GenericGenerator(name = "addressID", strategy = "guid")
private String addressID;
private String addressName;
private String content;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "address", cascade = CascadeType.ALL)
private Subscriber subscriber;
}
@Entity(name = "user")
@Table(name = "t_user")
public class Subscriber implements Serializable {
private static final long serialVersionUID = 9181139977020744196L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "user_id")
@GenericGenerator(name = "user_id", strategy = "guid")
private String userID;
private String username;
private LocalDate lastUpdate;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "addressID")
private Address address;
}
2017-01-07 15:12:53 DEBUG create table t_address (addressID varchar(36) not null, addressName varchar(255), content varchar(255), primary key (addressID))
2017-01-07 15:12:53 DEBUG create table t_user (userID varchar(36) not null, lastUpdate date, username varchar(255), addressID varchar(36), primary key (userID))
2017-01-07 15:12:53 DEBUG alter table t_user add constraint FKs3m591aubwmq2gs9pa690nu89 foreign key (addressID) references t_address (addressID)
上面两个实体类分别为用户表和用户地址表之间的双向一对一关联。
在用户表一侧设置外键,关联地址表主键,代码中需要在Address类中的@OneToOne注解中添加mappedBy表示由用户表一侧维护关联关系(即在用户表一侧添加外键关联)。
单向一对一关联
在双向一对一关联的基础上,只要在需要添加外键表的实体类上增加一对一关联即可,Subscriber 类不做变化,修改Address类:
public class Address implements Serializable {
private static final long serialVersionUID = 2390103918524410815L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "addressID")
@GenericGenerator(name = "addressID", strategy = "guid")
private String addressID;
private String addressName;
private String content;
}
双向一对多关联(双向多对一关联)
@Entity(name = "user")
@Table(name = "t_user")
public class Subscriber implements Serializable {
private static final long serialVersionUID = 9181139977020744196L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "user_id")
@GenericGenerator(name = "user_id", strategy = "guid")
private String userID;
private String username;
private LocalDate lastUpdate;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "roleID")
private Role role;
}
@Entity(name = "role")
@Table(name = "t_role")
public class Role implements Serializable {
private static final long serialVersionUID = -7982000043216756088L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "roleID")
@GenericGenerator(name = "roleID", strategy = "guid")
private String roleID;
private String roleName;
private LocalDateTime lastUpdate;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "role", cascade = CascadeType.ALL)
private Set<Subscriber> subscribers;
2017-01-07 15:22:31 DEBUG create table t_role (roleID varchar(36) not null, lastUpdate datetime, roleName varchar(255), primary key (roleID))
2017-01-07 15:22:31 DEBUG create table t_user (userID varchar(36) not null, lastUpdate date, username varchar(255), roleID varchar(36), primary key (userID))
2017-01-07 15:22:31 DEBUG alter table t_user add constraint FKc28rhpmp7an5dx89avr1y1m2q foreign key (roleID) references t_role (roleID)
多对一单项关联
在多对一双向关联的基础上修改Role类,去除subscribers:
public class Role implements Serializable {
private static final long serialVersionUID = -7982000043216756088L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "roleID")
@GenericGenerator(name = "roleID", strategy = "guid")
private String roleID;
private String roleName;
private LocalDateTime lastUpdate;
}
一对多单项关联
public class Role implements Serializable {
private static final long serialVersionUID = -7982000043216756088L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "roleID")
@GenericGenerator(name = "roleID", strategy = "guid")
private String roleID;
private String roleName;
private LocalDateTime lastUpdate;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Subscriber> subscribers;
}
public class Subscriber implements Serializable {
private static final long serialVersionUID = 9181139977020744196L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "user_id")
@GenericGenerator(name = "user_id", strategy = "guid")
private String userID;
private String username;
private LocalDate lastUpdate;
}
2017-01-07 15:31:29 DEBUG create table t_role (roleID varchar(36) not null, lastUpdate datetime, roleName varchar(255), primary key (roleID))
2017-01-07 15:31:29 DEBUG create table t_role_t_user (role_roleID varchar(36) not null, subscribers_userID varchar(36) not null, primary key (role_roleID, subscribers_userID))
2017-01-07 15:31:29 DEBUG create table t_user (userID varchar(36) not null, lastUpdate date, username varchar(255), addressID varchar(36), primary key (userID))
2017-01-07 15:31:29 DEBUG alter table t_role_t_user add constraint UK_3trydf2lqhdnq52vixb2ahoe0 unique (subscribers_userID)
2017-01-07 15:31:29 DEBUG alter table t_role_t_user add constraint FKrc5t9x0w3bhithg26cvbio0ar foreign key (subscribers_userID) references t_user (userID)
2017-01-07 15:31:29 DEBUG alter table t_role_t_user add constraint FKpxyafwfxy75buuokrq08fl4ob foreign key (role_roleID) references t_role (roleID)
最后会生成3张表,这里显而易见,当做多对多来处理
双向多对多关联
public class Subscriber implements Serializable {
private static final long serialVersionUID = 9181139977020744196L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "user_id")
@GenericGenerator(name = "user_id", strategy = "guid")
private String userID;
private String username;
private LocalDate lastUpdate;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "t_user_group", joinColumns = {@JoinColumn(name = "userID")},
inverseJoinColumns = {@JoinColumn(name = "groupID")})
private Set<Group> groups;
}
public class Group implements Serializable {
private static final long serialVersionUID = -1086629855135859375L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "groupID")
@GenericGenerator(name = "groupID", strategy = "guid")
private String groupID;
private String groupName;
@ManyToMany(mappedBy = "groups")
private Set<Subscriber> subscribers;
}
2017-01-07 15:47:57 DEBUG create table t_group (groupID varchar(36) not null, groupName varchar(255), primary key (groupID))
2017-01-07 15:47:58 DEBUG create table t_user (userID varchar(36) not null, lastUpdate date, username varchar(255), addressID varchar(36), roleID varchar(36), primary key (userID))
2017-01-07 15:47:58 DEBUG create table t_user_group (userID varchar(36) not null, groupID varchar(36) not null, primary key (userID, groupID))
2017-01-07 15:47:58 DEBUG alter table t_user_group add constraint FKfgcvmarajos52c6isr5jbmtcx foreign key (groupID) references t_group (groupID)
2017-01-07 15:47:58 DEBUG alter table t_user_group add constraint FKbovsdkvtssoue3hacl3ss4pb foreign key (userID) references t_user (userID)
单项多对多关联
在多项多对多关联上的某一方去除@ManyToMany即可。例如在Group一方:
public class Group implements Serializable {
private static final long serialVersionUID = -1086629855135859375L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "groupID")
@GenericGenerator(name = "groupID", strategy = "guid")
private String groupID;
private String groupName;
}
单向一对一主键关联(共享主键)
public class Address implements Serializable {
private static final long serialVersionUID = 2390103918524410815L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "addressID")
@GenericGenerator(name = "addressID", strategy = "foreign", parameters = @Parameter(name = "property", value = "subscriber"))
private String addressID;
private String addressName;
private String content;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn(name = "addressID", referencedColumnName = "userID")
private Subscriber subscriber;
}
public class Subscriber implements Serializable {
private static final long serialVersionUID = 9181139977020744196L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "user_id")
@GenericGenerator(name = "user_id", strategy = "guid")
private String userID;
private String username;
private LocalDate lastUpdate;
}
Session session = this.sessionFactory.getCurrentSession();
session.getTransaction().begin();
Subscriber subscriber = new Subscriber("username");
Address address = new Address("addressName", "content");
address.setSubscriber(subscriber);
session.persist(address);
session.getTransaction().commit();
session.close();
2017-01-08 16:26:25 DEBUG create table t_address (addressID varchar(36) not null, addressName varchar(255), content varchar(255), primary key (addressID))
2017-01-08 16:26:25 DEBUG create table t_user (userID varchar(36) not null, lastUpdate date, username varchar(255), primary key (userID))
2017-01-08 16:26:25 DEBUG select uuid()
2017-01-08 16:26:25 WARN HHH000113: GUID identifier generated: 53c6e9ec-26cc-1035-ad8a-9e22cd9fb5ab
2017-01-08 16:26:25 DEBUG insert into t_user (lastUpdate, username, userID) values (?, ?, ?)
2017-01-08 16:26:25 TRACE binding parameter [1] as [DATE] - [2017-01-08]
2017-01-08 16:26:25 TRACE binding parameter [2] as [VARCHAR] - [username]
2017-01-08 16:26:25 TRACE binding parameter [3] as [VARCHAR] - [53c6e9ec-26cc-1035-ad8a-9e22cd9fb5ab]
2017-01-08 16:26:25 DEBUG insert into t_address (addressName, content, addressID) values (?, ?, ?)
2017-01-08 16:26:25 TRACE binding parameter [1] as [VARCHAR] - [addressName]
2017-01-08 16:26:25 TRACE binding parameter [2] as [VARCHAR] - [content]
2017-01-08 16:26:25 TRACE binding parameter [3] as [VARCHAR] - [53c6e9ec-26cc-1035-ad8a-9e22cd9fb5ab]
运行测试代码后,发出的建表语句中没有添加外键关联。在插入数据时,只会生成一个主键,Subscriber和Address两个实体共用一个主键
双向一对一主键关联(共享主键)
在Subscriber中添加如下代码即可
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "subscriber")
@PrimaryKeyJoinColumn(name = "userID", referencedColumnName = "addressID")
private Address address;
运行测试代码效果和单项一对一主键关联一致