我有一个单向关系
Country
和
Governorate
第一个是所有者,下面是它们的实现:
Country.java
@RequiredArgsConstructor
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@Entity
public class Country {
@Id
@NotBlank
@Size(max = 3)
@NonNull
@Setter
private String isoCode;
@Column(unique = true, nullable = false)
@NotBlank
@Size(max = 50)
@NonNull
@Setter
private String name;
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
@EqualsAndHashCode.Exclude
private List<Governorate> governorates = new ArrayList<>();
}
Governorate.java
@NoArgsConstructor
@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@Entity
public class Governorate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
@NotBlank
@Size(max = 50)
@Setter
@NonNull
private String name;
}
我试图在启动时填充数据库,所以我实现了一个
CommandLineRunner
从a阅读的类
json
文件填充为
countries
以及它们各自的
governorates
并映射到以下列表
国家
像这样:
CountriesInitializer.java
@Component
public class CountriesInitilizer extends Initializer<Country>{
private static final Logger logger = LoggerFactory.getLogger(CountriesInitilizer.class);
private static final String JSON_FILE = "com/evalia/backend/countries.json";
@Autowired
CountryRepository repository;
@Override
void preLoad(Class<Country> clazz, String filePath) {
try (InputStream stream = ResourceUtils.loadResource(filePath)) {
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<Country>> recordTypes = new TypeReference<List<Country>>() {};
List<Country> countries = mapper.readValue(stream, recordTypes);
for(Country c: countries) {
repository.save(c);
}
} catch (IOException e) {
InitializationException ex = InitializationException.build(clazz.getName(), e);
logger.error("Could not pre-load entity!", ex);
throw ex;
}
}
@Override
public void run(String... args) throws Exception {
if (!InitializersUtils.isLoaded(repository)) {
preLoad(Country.class, JSON_FILE);
}
}
}
这里的问题是,每当我启动应用程序,这个初始化器开始保存它抛出的数据时
ConstraintsViolationException
具有以下堆栈跟踪:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at com.evalia.backend.EvaliaApplication.main(EvaliaApplication.java:10) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
Caused by: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:571) ~[spring-orm-5.3.29.jar:5.3.29]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.29.jar:5.3.29]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.29.jar:5.3.29]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.29.jar:5.3.29]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174) ~[spring-data-jpa-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.29.jar:5.3.29]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.29.jar:5.3.29]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.29.jar:5.3.29]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241) ~[spring-aop-5.3.29.jar:5.3.29]
at com.sun.proxy.$Proxy143.save(Unknown Source) ~[na:na]
at com.evalia.backend.initializers.CountriesInitilizer.preLoad(CountriesInitilizer.java:41) ~[classes/:na]
at com.evalia.backend.initializers.CountriesInitilizer.run(CountriesInitilizer.java:55) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:768) ~[spring-boot-2.7.15-SNAPSHOT.jar:2.7.15-SNAPSHOT]
... 10 common frames omitted
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.29.jar:5.3.29]
... 27 common frames omitted
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.evalia.backend.models.Governorate] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=name, rootBeanClass=class com.evalia.backend.models.Governorate, messageTemplate='must not be blank'}
]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:188) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:78) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:329) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:286) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:801) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:510) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:434) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:543) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:474) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:437) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3303) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2438) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
... 28 common frames omitted
有什么想法吗?
环境
:
Java
11
,
弹簧靴:
2.7.15-SNAPSHOT
我试着在
BeanValidationEventListener
如堆栈中所述
Exception
被抛出后,我发现了一些有趣的东西,第一个被传递进行验证的实体是
国家
实例附带了它的值,但当它是
省份
轮到时,它们将被传递给验证,其值设置为
null
,这是bug还是我做错了什么?
非常感谢。