我正在努力将Hibernate用于现有的遗留模式(我无法更新它(,并且有一个奇怪的情况:
表用户:
- db_id PK
- user_id(唯一约束(
- 。其他列
表地址
- db_id PK
- user_id(唯一约束(
- 。常用地址列
这些具有一对一的关系。我正在创建以下@Entity
带注释的类。
class UserEntity {
@Id
@GeneratedValue
private UUID dbId;
private String userId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id", referencedColumnName = "user_id")
private AddressEntity address;
}
class AddressEntity {
@Id
@GeneratedValue
private UUID dbId;
private String userId;
@OneToOne
private UserEntity user;
}
Hibernate认为这是一个重复的列定义,这是合理的。但是,由于在地址表中我没有 FK 或 PK user_id,我不确定如何将其传达给 Hibernate。我试图寻找类似的但没有成功,所以任何建议将不胜感激。
更新
可能有更好的方法来实现这一点,比如使用 @NaturalId
,但我无法让它与 Hibernate 5.2.12.Final 一起使用。
但是,@JoinFormula
救援:
@Entity
@Table(name = "T_USER")
public class UserEntity implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Type(type = "uuid-char")
@Column(name = "DB_ID", length = 36)
private UUID dbId;
@Column(name = "USER_ID", nullable = false, unique = true)
private String userId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(select x.DB_ID from T_ADDRESS x where x.USER_ID=USER_ID)")
private AddressEntity address;
@Override
public String toString()
{
return String.format("%s: dbId=%s, userId=%s, address=%s",
getClass().getSimpleName(),
dbId,
userId,
address != null ? address.getDbId() : null);
}
}
@Entity
@Table(name = "T_ADDRESS")
public class AddressEntity implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Type(type = "uuid-char")
@Column(name = "DB_ID", length = 36, nullable = false, unique = true)
private UUID dbId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID")
private UserEntity user;
@Override
public String toString()
{
return String.format("%s: dbId=%s, user=%s",
getClass().getSimpleName(),
dbId,
user != null ? user.getDbId() : null);
}
}
使用 MySQL8 对其进行了测试:
CREATE TABLE `t_user` (
`DB_ID` varchar(36) NOT NULL,
`USER_ID` varchar(255) NOT NULL,
PRIMARY KEY (`DB_ID`),
UNIQUE KEY `UK_kvueux8cmkdekeqhrs7pumkwi` (`USER_ID`)
) ENGINE=InnoDB
CREATE TABLE `t_address` (
`DB_ID` varchar(36) NOT NULL,
`USER_ID` varchar(255) DEFAULT NULL,
PRIMARY KEY (`DB_ID`),
KEY `FK1s9gxk3we3yq11hjw5hp7ahp5` (`USER_ID`),
CONSTRAINT `FK1s9gxk3we3yq11hjw5hp7ahp5` FOREIGN KEY (`USER_ID`) REFERENCES `t_user` (`user_id`)
) ENGINE=InnoDB
有了这个快速的肮脏启动器:
public class Main
{
public static void main(String[] args)
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test_hibernate");
try
{
EntityManager em = emf.createEntityManager();
try
{
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try
{
UserEntity user = new UserEntity();
user.setDbId(UUID.randomUUID());
user.setUserId("user_" + System.nanoTime());
em.persist(user);
AddressEntity address = new AddressEntity();
address.setDbId(UUID.randomUUID());
address.setUser(user);
user.setAddress(address);
em.persist(address);
transaction.commit();
System.out.println("persisted user: " + user);
System.out.println("persisted address: " + address);
}
catch(Exception e)
{
e.printStackTrace();
transaction.rollback();
}
}
finally
{
em.close();
}
EntityManager em2 = emf.createEntityManager();
try
{
List<UserEntity> userList = em2.createQuery("select x from UserEntity x", UserEntity.class).getResultList();
userList.forEach(x -> System.out.println("loaded user: " + x));
List<AddressEntity> addressList = em2.createQuery("select x from AddressEntity x", AddressEntity.class).getResultList();
addressList.forEach(x -> System.out.println("loaded address: " + x));
}
finally
{
em2.close();
}
}
finally
{
emf.close();
}
System.out.println("ok");
}
}
产生了这些结果:
persisted user: UserEntity: dbId=a22db668-eda0-4de1-83ae-98a7cd8738bd, userId=user_789235935853200, address=c17c0c28-603e-4961-90b0-16232346e47b
persisted address: AddressEntity: dbId=c17c0c28-603e-4961-90b0-16232346e47b, user=a22db668-eda0-4de1-83ae-98a7cd8738bd
loaded user: UserEntity: dbId=a22db668-eda0-4de1-83ae-98a7cd8738bd, userId=user_789235935853200, address=c17c0c28-603e-4961-90b0-16232346e47b
loaded address: AddressEntity: dbId=c17c0c28-603e-4961-90b0-16232346e47b, user=a22db668-eda0-4de1-83ae-98a7cd8738bd
一对一关系定义如下:
class UserEntity {
....
@Column(length = 20)
private String userId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "userId", referencedColumnName = "userId", insertable = false, updatable = false)
private AddressEntity address;
}
class AddressEntity {
....
@Column(length = 20)
private String userId;
.....
}