java—在jpa hibernate中通过非主键进行一对多关联的任何方法

byqmnocz  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(332)

我正在尝试通过父级的非主键进行一对多关联。我正在使用jpa2.1和hibernate。我发现了几个类似的问题。但我觉得我的情况有点不同。
我有两张table: ProfileBasic 以及 Phonenumber .

@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`);

我还有别的table,做了好几张 views 从那些table上,有些箱子 profile_idPrimary Key 在那些观点上。我做得很成功 one to many 来自的关联 views ,其中主键是 profile_id . 但我有一个观点,在哪里 profile_id 不是pk,因此在取数时,它生成的查询是正确的,但值是错误的。

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 .
我在书中看到几个问题 stackoverflow . 现在我想知道:有没有什么方法可以让我把 phone numberone-to-many ,在哪里 profile_id 不是pk。如果不可能的话,我就得看每一行的电话号码 views .
查看实体:

@Entity
@Table(name = "donner_assing_show")
public class DonnerAssingShow implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "donner_assingment_id")
    private long donnerAssingmentId;

    @Size(max = 255)
    @Column(name = "agent_id")
    private String agentId;
    @Size(max = 255)
    @Column(name = "donner_id")
    private String donnerId;
    @Size(max = 255)
    @Column(name = "assing_date")
    private String assingDate;
    @Lob
    @Size(max = 2147483647)
    @Column(name = "assing_note")
    private String assingNote;
    @Size(max = 255)
    @Column(name = "need_date")
    private String needDate;
    @Size(max = 255)
    @Column(name = "post_id")
    private String postId;
    @Size(max = 255)
    @Column(name = "blood_manage_status")
    private String bloodManageStatus;
    @Basic(optional = false)
    @NotNull
    @Column(name = "profile_id")
    private long profileId;
    @Size(max = 255)
    @Column(name = "available")
    private String available;
    @Size(max = 255)
    @Column(name = "birth_date")
    private String birthDate;
    @Size(max = 255)
    @Column(name = "blood_Group")
    private String bloodGroup;
    @Size(max = 255)
    @Column(name = "care_of")
    private String careOf;
    // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
    @Size(max = 255)
    @Column(name = "email")
    private String email;
    @Size(max = 255)
    @Column(name = "gender")
    private String gender;
    @Size(max = 255)
    @Column(name = "marital_status")
    private String maritalStatus;
    @Size(max = 255)
    @Column(name = "name")
    private String name;
    @Size(max = 255)
    @Column(name = "profession")
    private String profession;
    @Size(max = 255)
    @Column(name = "religion")
    private String religion;
    @Size(max = 255)
    @Column(name = "user_id")
    private String userId;

    @OneToMany
    //    @OneToMany(fetch = FetchType.EAGER)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "profile_id")
    private List<PhoneNumber> phone_number;

    //    @OneToMany
    @OneToMany(fetch = FetchType.EAGER)
//    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "profile_id")
    private List<Address> addressList;

    // constructor-getter/setters
}

项目的github链接
代码的单元测试
项目转储数据

baubqpgj

baubqpgj1#

联接列不必是主键的一部分,也不必在两个表中使用相同的列名。可以使用“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
}
vx6bjr1n

vx6bjr1n2#

应按以下方式更正Map:

@Entity
public class ProfileBasic {

   //....some columns.

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "profile", 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;
}

评论:
这个 @JoinColumn 注解应该用在拥有外键列的一侧(这是 PhoneNumber 在你的情况下)。
没有必要使用 referencedColumnName 当fk裁判到pk栏时。
遵循java命名约定是很好的。所以,最好使用 phoneNumbers 作为属性名而不是 phone_number .

相关问题