如何解决JPA 复合键和级联
我想同时使用 JPA CASCADE 来持久化父级及其子级。父类 (Filter
) 有一个复合键 (PKFilter
)。奥尔多,子类 (FilterRule
) 有其复合键 (PKFilterRule
)。主键类用 @Embeddable
注释,它们被引用为 @EmbeddedId
。
PKFilter:
@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 创建过滤器,然后持久化过滤器对象:
@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,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
我们错过了什么? 非常感谢!
解决方法
找到解决办法:
将 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);
}
一切都按预期进行。 谢谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。