hibernate 非键列的@OneToOneMap

eqqqjvef  于 2023-10-23  发布在  其他
关注(0)|答案(3)|浏览(90)

我正在为现有的遗留模式使用Hibernate(我无法更新它),有一个奇怪的情况:

表用户:

  1. db_id主键
  2. user_id(唯一约束)
    1.。其他专栏

表地址

  1. db_id主键
  2. user_id(唯一约束)
    1..常用地址栏
    它们有一一对应的关系。我正在创建以下@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认为这是合理的重复列定义。然而,由于在Address表中,我没有将user_id作为FK或PK,我不知道如何将其传达给Hibernate。我试图寻找一个类似的,但没有成功,所以任何建议将不胜感激。

0qx6xfy6

0qx6xfy61#

已删除

也许有更好的方法来实现这一点,比如使用@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
rwqw0loc

rwqw0loc2#

一对一关系定义如下:

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;

  .....
}
toe95027

toe950273#

对于@OneToOne关系在两个实体中的使用,当你需要在不存在的列端使用它时,你必须将它Map到相应的字段,所以你可以像这样使用它:

class UserEntity {
    @Id
    @GeneratedValue
    private UUID dbId;

    private String userId;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private AddressEntity address;
}

class AddressEntity {
    @Id
    @GeneratedValue
    private UUID dbId;

    private String userId;

    @OneToOne(mappedBy = "address")
    private UserEntity user;
}

相关问题