【问题标题】:Spring Boot 2, Spring 5 JPA: Dealing with multiple OneToMany JoinTablesSpring Boot 2、Spring 5 JPA:处理多个 OneToMany JoinTables
【发布时间】:2021-04-17 01:12:23
【问题描述】:

不确定为具有多个实体的实体实施 CrudRepository 的最佳方法 @OneToMany 与 @JoinTable 的关联

@Entity
@Table(name = "contact", uniqueConstraints = {@UniqueConstraint(columnNames ={"first_name","last_name"})})
@SuppressWarnings("PersistenceUnitPresent")
public class Contact extends Auditable implements Serializable {

    @Id
    @Column(name = "contact_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "contact_generator")
    @SequenceGenerator(name = "contact_generator", sequenceName = "contact_seq", allocationSize = 50)
    private Long contactId;

    @Column(name = "first_name", nullable = false)
    private String firstName;
    
    @Column(name = "last_name", nullable = false)
    private String lastName;
    
    @Column(name = "middle_name", nullable = true)
    private String middleName;
    
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinTable( 
        name = "contact_phone"
    )
    private List<Phone> phoneNumbers = new ArrayList<>();
    
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinTable(name = "contact_email")
    private List<EmailAddress> emailAddresses = new ArrayList<>();
public interface ContactRepo  extends CrudRepository<Contact, Long> {
    
    List<Contact> findByLastNameContainingIgnoreCase(String lastName);

}

我有 FetchType.LAZY,所以我没有从 2 个笛卡尔积中得到 MultipleBagFetchException。 所以我知道我需要将 2 个连接分开,这是我坚持最佳解决方案的地方。 放入可以访问 EntityManager 并编写 2 个连接的自定义 repo 和 customImpl 类? 我不是疯了,让 Java 通过 Set 来处理笛卡尔,也不是拥有 FetchType.EAGER 并用另一个查询处理另一个??

生成:

    create table contact (
       contact_id bigint not null,
        create_tm timestamp not null,
        created_by varchar(255) not null,
        updated_tm timestamp not null,
        updated_by varchar(255) not null,
        first_name varchar(255) not null,
        last_name varchar(255) not null,
        middle_name varchar(255),
        primary key (contact_id)
    )
    create table email_address (
       email_id bigint not null,
        email_addr varchar(255) not null,
        email_type varchar(255),
        primary_addr boolean default false,
        primary key (email_id)
    )

    create table contact_email (
       Contact_contact_id bigint not null,
        emailAddresses_email_id bigint not null
    )

    create table phone (
       phone_id bigint not null,
        phone_nbr varchar(255) not null,
        phone_type varchar(255),
        primary_ph boolean default false,
        primary key (phone_id)
    )

    create table contact_phone (
       Contact_contact_id bigint not null,
        phoneNumbers_phone_id bigint not null
    )

奇怪的是我的 JpaDataTests 工作发现。 find all 和 findByLastNameContainingIgnoreCase 返回电话号码和电子邮件地址。

但是,服务不会。

    @Autowired
    private ContactRepo contactRepo;
    
    @Override
    public List<Contact> findAllContacts() throws GcaServiceException {
        try {
            Iterable<Contact> iter = contactRepo.findAll();
            return IteratorUtils.toList(iter.iterator());
        } catch(DataAccessException e) {
            throw new GcaServiceException(e.getMessage());
        }
    }
    
    @Override
    public List<Contact> findByLastName(String lastName) throws GcaServiceException {
        try {
            return contactRepo.findByLastNameContainingIgnoreCase(lastName);
        } catch (DataAccessException e) {
            throw new GcaServiceException(e.getMessage());
        }
    }
[
      {
      "createTm": "2021-01-11T16:27:19.995011",
      "createdBy": "UncleMoose",
      "updatedBy": "UncleMoose",
      "updateTm": "2021-01-11T16:27:19.995011",
      "contactId": 1,
      "firstName": "Bruce",
      "lastName": "Randall",
      "middleName": null,
      "phoneNumbers": [],
      "emailAddresses": []
   },
      {
      "createTm": "2021-01-11T16:27:19.996009",
      "createdBy": "UncleMoose",
      "updatedBy": "UncleMoose",
      "updateTm": "2021-01-11T16:27:19.996009",
      "contactId": 51,
      "firstName": "Boss",
      "lastName": "Randall",
      "middleName": null,
      "phoneNumbers": [],
      "emailAddresses": []
   }
]

【问题讨论】:

    标签: spring spring-boot jpa spring-data-jpa


    【解决方案1】:

    DataJpaTest 与手动集成测试差异的部分奥秘在于我决定查看地图并确保我没有走错 Google 路线。我打开了 H2 控制台,发现即使插入发生了 Join Tables 也是空的?但是,我注意到在实时测试和自动测试之间我得到了不同的 Join Table 列名称。

    解决方案是明确命名联接表列。看来 Spring 已经处理了一个实体中具有多个 OneToMany JoinTable 属性的 MultipleBagFetchException 问题。

        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
        @JoinTable( 
            name = "contact_phone"
           ,joinColumns = @JoinColumn(name = "contact_id")
           ,inverseJoinColumns = @JoinColumn(name = "phone_id")
        )
        private List<Phone> phoneNumbers = new ArrayList<>();
        
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
        @JoinTable(
            name = "contact_email"
           ,joinColumns = @JoinColumn(name = "contact_id")
           ,inverseJoinColumns = @JoinColumn(name = "email_id")
        )
        private List<EmailAddress> emailAddresses = new ArrayList<>();
    

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 2020-02-25
      • 2018-10-14
      • 1970-01-01
      • 2020-07-11
      • 2021-12-15
      • 2019-05-17
      • 1970-01-01
      • 2019-03-07
      相关资源
      最近更新 更多