通过JPA休眠中的非主键进行一对多关联的任何方法

问题描述

我正在尝试通过父级的非主键进行一对多关联。我在休眠状态下使用JPA 2.1。我发现了几个类似的问题。但是我认为我的情况有些不同。

我有两个表: ProfileBasicPhonenumber

    @Entity
public class ProfileBasic {
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       @Column(name = "profile_id")
       private Long id;     
       
       //....some columns.
       
        @OnetoMany(cascade = CascadeType.ALL,orphanRemoval = true)
        @JoinColumn(name = "profile_id")
        private List<PhoneNumber> phone_number;

        // getters-setters
}


public class PhoneNumber implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    // getters-setters and other columns
    
}

数据库表:

CREATE TABLE `profilebasic` (
  `profile_id` bigint(20) NOT NULL,`available` varchar(255) DEFAULT NULL,`birth_date` varchar(255) DEFAULT NULL,`blood_Group` varchar(255) DEFAULT NULL,`care_of` varchar(255) DEFAULT NULL,`email` varchar(255) DEFAULT NULL,`gender` varchar(255) DEFAULT NULL,`marital_status` varchar(255) DEFAULT NULL,`name` varchar(255) DEFAULT NULL,`profession` varchar(255) DEFAULT NULL,`religion` varchar(255) DEFAULT NULL,`user_id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for table `profilebasic`
--
ALTER TABLE `profilebasic`
  ADD PRIMARY KEY (`profile_id`);


    CREATE TABLE `phonenumber` (
      `id` bigint(20) NOT NULL,`number` varchar(255) DEFAULT NULL,`profile_id` bigint(20) DEFAULT NULL
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for table `phonenumber`
--
ALTER TABLE `phonenumber`
  ADD PRIMARY KEY (`id`),ADD KEY `FK8sfxu3ejjpklkd3njt3767ape` (`profile_id`);

--
-- Constraints for table `phonenumber`
--
ALTER TABLE `phonenumber`
  ADD CONSTRAINT `FK8sfxu3ejjpklkd3njt3767ape` FOREIGN KEY (`profile_id`) REFERENCES `profilebasic` (`profile_id`);

我还有其他表,并从那些表中制作了多个views,其中某些情况下profile_id是那些视图上的Primary Key。我已经成功完成了one to many的{​​{1}}关联,其中主键为views。但是我有一个观点,profile_id不是PK,由于在获取时,它会生成正确的查询但值不正确。

profile_id

此处Hibernate: select phone_numb0_.profile_id as profile_3_18_0_,phone_numb0_.id as id1_18_0_,phone_numb0_.id as id1_18_1_,phone_numb0_.number as number2_18_1_ from PhoneNumber phone_numb0_ where phone_numb0_.profile_id=? 2020-08-23 04:00:48.396 TRACE 9292 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [21451] 错误的值:parameter [1] as [BIGINT] - [21451]的PK,其中正确的值为view。但是正如我之前所讲的,这在视图的主键为1134的地方有效。

我在profile_id中看到了几个问题。现在我想知道:有什么方法可以将stackoverflowphone number关联,其中one-to-many不是PK。如果不可能,我必须读取profile_id每行的电话号码。

查看实体:

views

GitHub Link of the project where stacked

Unit Test of the code

Dump Data of the project

解决方法

join列不必是主键的一部分,也不必在两个表中使用相同的列名。您可以使用“ referenceColumnName”指定要加入的列。

@Entity
public class ProfileBasic 
{
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       @Column(name = "profile_id")
       private Long id;     
       
       //....some columns.
       
        @OneToMany(cascade = CascadeType.ALL,mappedBy = "profile",orphanRemoval = true)
        private List<PhoneNumber> phone_number;

        // getters-setters
}
public class PhoneNumber implements Serializable 
{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "profile_id")
    @JoinColumn(name = "profile_id",referencedColumnName = "profile_id",nullable = false)
    private ProfileBasic profile;
    
    // getters-setters
}
,

您应通过以下方式更正映射:

@Entity
public class ProfileBasic {
       
   //....some columns.
   
   @OneToMany(cascade = CascadeType.ALL,orphanRemoval = true)
   private List<PhoneNumber> phoneNumbers;
}

@Entity
public class PhoneNumber implements Serializable {

    // getters-setters and other columns
    
    @ManyToOne
    @JoinColumn(name = "profile_id",nullable = false)
    private ProfileBasic profile;
}

评论:

  1. 应该在拥有外键列的一侧使用@JoinColumn注释(在您的情况下为PhoneNumber)。

  2. 当FK引用PK列时,不必使用referencedColumnName

  3. 最好遵循java naming conventions。因此,最好使用phoneNumbers作为属性名称,而不要使用phone_number