0

我想同时使用 JPA CASCADE 来持久化父级及其子级。父类 ( Filter) 有一个复合键 ( PKFilter)。Aldo,子类 ( FilterRule) 有它的复合键 ( PKFilterRule)。主键类带有注释,@Embeddable它们被引用为@EmbeddedId.

PK过滤器:

@Getter
@Setter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("JpaDataSourceORMInspection")
@EqualsAndHashCode
public class PkFilter implements Serializable {

    @Column(name = "CUSTOMER_ID")
    private int customerId;

    @Column(name = "COMPANY_ID")
    private int companyId;

    @Column(name = "FILTER_ID")
    private String filterId;

}

PKFilterRule:

@Getter
@Setter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("JpaDataSourceORMInspection")
@EqualsAndHashCode
public class PkFilterRule implements Serializable {

    @Column(name = "CUSTOMER_ID")
    private int customerId;

    @Column(name = "COMPANY_ID")
    private int companyId;

    @Column(name = "FILTER_ID")
    private String filterId;

    @Column(name = "FILTER_RULE")
    private String filterRule;

    @Column(name = "FILTER_KEY")
    private String filterKey;

}

筛选

@Getter
@Setter
@Entity
@EqualsAndHashCode
@Table( name = "IOND_FILTERS")
public class Filter {

    @EmbeddedId
    private PkFilter pkFilter;

    @Column(name = "FILTER_TARGET")
    private String filterTarget;

    @Column(name = "FILTER_STATUS")
    private String filterStatus;

    @OneToMany(mappedBy = "filter", cascade = CascadeType.ALL)
    private List<FilterRule> rules;

}

过滤规则

@Getter
@Setter
@Entity
@EqualsAndHashCode
@Table( name = "IOND_FILTERS_RULES")
public class FilterRule {

    @EmbeddedId
    private PkFilterRule pkFilterRule;

    @MapsId
    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID")
    @JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID")
    @JoinColumn(name = "FILTER_ID", referencedColumnName = "FILTER_ID")
    private Filter filter;

}

作为测试,我们尝试使用 FilterItem 创建一个 Filter,然后持久化 Filter 对象:

@RunWith(SpringRunner.class)
@SpringBootTest()
@TestPropertySource(locations = {"classpath:application-test.properties"})
public class ProductsApplicationTests {

    @Autowired
    private FilterRepository filterRepository;

    @Test
    @Transactional
    @Commit
    public void test() {

        var uuid = UUID.randomUUID().toString();

        //Cria um novo Filtro
        var filter = new Filter();
        filter.setPkFilter(
                new PkFilter(208, 210, uuid)
        );

        filter.setFilterTarget("ET");
        filter.setFilterStatus("EN");

        //Adiciona alguns itens
        var filterRule = new FilterRule();
        filterRule.setPkFilterRule(
                new PkFilterRule(208, 210, uuid, "RULE", "KEY")
        );
        filterRule.setFilter(filter);

        filter.setRules(Collections.singletonList(filterRule));

        filterRepository.saveAndFlush(filter);

    }

}

而且,作为例外,我们得到:

Caused by: java.lang.IllegalArgumentException: Can not set int field api.products.domain.model.keys.PkFilterRule.companyId to api.products.domain.model.keys.PkFilter
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at java.base/jdk.internal.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
    at java.base/java.lang.reflect.Field.getInt(Field.java:594)
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62)
    ... 97 more

我们缺少什么?非常感谢!

4

1 回答 1

0

找到了解决方案:

将 PkFilterRule 更改为使用 PkFilter,如下所示:

@Getter
@Setter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("JpaDataSourceORMInspection")
@EqualsAndHashCode
public class PkFilterRule implements Serializable {

    private PkFilter pkFilter; //<-------HERE

    @Column(name = "FILTER_RULE")
    private String filterRule;

    @Column(name = "FILTER_KEY")
    private String filterKey;

}

然后,将@MapsID 更改为如下:

@Getter
@Setter
@Entity
@EqualsAndHashCode
@Table(name = "IOND_FILTERS_RULES")
public class FilterRule {

    @EmbeddedId
    private PkFilterRule pkFilterRule;

    @MapsId("pkFilter") //<------------------------------------ HERE
    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID")
    @JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID")
    @JoinColumn(name = "FILTER_ID", referencedColumnName = "FILTER_ID")
    private Filter filter;

}

最后但同样重要的是,更改了测试:

@Test
@Transactional
@Commit
public void test() {

    var uuid = UUID.randomUUID().toString();

    //Cria um novo Filtro
    var filter = new Filter();
    filter.setPkFilter(
            new PkFilter(208, 210, uuid)
    );

    filter.setFilterTarget("ET");
    filter.setFilterStatus("EN");

    //Adiciona alguns itens
    var filterRule = new FilterRule();
    filterRule.setPkFilterRule(
            new PkFilterRule(filter.getPkFilter(), //<--------HERE
            "RULE", "KEY")
    );
    filterRule.setFilter(filter);

    filter.setRules(Collections.singletonList(filterRule));

    filterRepository.saveAndFlush(filter);

}

一切都按预期工作。谢谢!

于 2021-05-06T19:48:10.570 回答