繁体   English   中英

在JPA-hibernate中通过非主键进行一对多关联的任何方式

[英]Any way to do one-to-many association by non primary key in JPA-hibernate

我正在尝试通过父项的非主键进行一对多关联。 我在休眠中使用 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 我已经成功地从views完成one to many关联,其中主键是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]是错误的值: view PK ,其中正确的值将是1134 但正如我之前所说,这是在视图的主键是profile_id

我在stackoverflow看到了几个问题。 现在我想知道:有什么方法可以通过one-to-many关联phone number ,其中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 链接

代码的单元测试

转储项目数据

连接列不需要是主键的一部分,或者在两个表中使用相同的列名。 您可以使用“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, 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;
}

注释:

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

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

  3. 最好遵循java 命名约定 因此,最好使用phoneNumbers作为属性名称而不是phone_number

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM