我正在与Kotlin和Spring(通过Springboot)合作。我的身价为2.0.0-m3,一切都正确。
我决定跳到M4。然后,我遇到了一些麻烦。
我得到以下堆栈跟踪:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:107)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:242)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.reflect.jvm.ReflectJvmMapping.getJavaConstructor, parameter $receiver
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:740)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:138)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
... 25 more
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.reflect.jvm.ReflectJvmMapping.getJavaConstructor, parameter $receiver
at kotlin.reflect.jvm.ReflectJvmMapping.getJavaConstructor(ReflectJvmMapping.kt)
at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers$2.lambda$discover$2(PreferredConstructorDiscoverer.java:169)
at java.util.Optional.orElseGet(Optional.java:267)
at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers$2.discover(PreferredConstructorDiscoverer.java:165)
at org.springframework.data.mapping.model.PreferredConstructorDiscoverer.discover(PreferredConstructorDiscoverer.java:77)
at org.springframework.data.mapping.model.BasicPersistentEntity.<init>(BasicPersistentEntity.java:93)
at org.springframework.data.jpa.mapping.JpaPersistentEntityImpl.<init>(JpaPersistentEntityImpl.java:54)
at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.createPersistentEntity(JpaMetamodelMappingContext.java:66)
at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.createPersistentEntity(JpaMetamodelMappingContext.java:40)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:376)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:343)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:469)
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:90)
at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:43)
at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:141)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1761)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1698)
... 40 more
这是我的代码:
实体
@Entity
@Table(name = "code_list")
class CodeList : Serializable {
/* ----- FIELDS ----- */
//endregion
//region GET / SET methods
@Id
@Column(name = "NO_SECSOC", nullable = false)
var secSocId: Long? = null
@Id
@Column(name = "ID_CODE_LIST")
var codelistId: String? = null
@Id
@Column(name = "NO_COM_PARITAIRE")
var comParitaireId: String? = null
@Id
@Column(name = "NO_EMPLOYEUR")
var employerId: Long? = null
@Id
@Column(name = "NO_CCTE")
var ccteId: String? = null
@Id
@Column(name = "VAL_NUM")
var numberValue: Long? = null
@Id
@Column(name = "VAL_STRING")
var stringValue: String? = null
@Column(name = "DT_DEBUT_EFFET")
var startEffectDate: LocalDate? = null
@Column(name = "DT_FIN_EFFET")
var endEffectDate: LocalDate? = null
@Embedded
var label: MultilingualString? = null
/** Set the type of value to use */
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@NotFound(action = NotFoundAction.IGNORE)
@JoinColumn(name = "ID_CODE_LIST", insertable = false, updatable = false)
var codeListType: CodeListType? = null
//region Constructor
constructor() {}
constructor(secSocId: Long?, employerId: Long?, ccteId: String, codeListId: String) {
this.secSocId = secSocId
this.employerId = employerId
this.ccteId = ccteId
this.codelistId = codeListId
}
//endregion
}
存储库
@Component
class CodeListRepository {
@Autowired
lateinit var entityManager: EntityManager
fun findCodeListLikeCB(predicateMap: Map<String, Any?>): List<CodeList> {
val cb = entityManager.criteriaBuilder
val query = cb.createQuery(CodeList::class.java)
val codeListRoot = query.from(CodeList::class.java)
val predicateList: ArrayList<Predicate> = ArrayList()
// foreach to build predicateList
for ((key, value) in predicateMap) {
if (value != null) {
// For a list, needed to add a condition IN
if (value is List<*>)
predicateList.add(codeListRoot.get<Any>(key).`in`(value))
//For a date, needed to add condition
// For start date --> before param start date
// For end date --> after param date or null
if (value is LocalDate) {
if (key == "startEffectDate") {
predicateList.add(cb.lessThanOrEqualTo(codeListRoot.get("startEffectDate"), value))
}
if (key == "endEffectDate") {
// cb.conjunction allow to add parenthesis to the predicate
val predicate = cb.conjunction()
predicate.expressions.add(cb.or(cb.greaterThan(codeListRoot.get("endEffectDate"), value), cb.isNull(codeListRoot.get<Any>("endEffectDate"))))
predicateList.add(predicate)
}
}
if (value !is LocalDate && value !is List<*>) {
predicateList.add(cb.equal(codeListRoot.get<Any>(key), value))
}
}
}
query.select(codeListRoot).where(cb.and(*predicateList.toTypedArray()))
return entityManager.createQuery(query).resultList
}
}
测试类
@ComponentScan("be.groups")
@EntityScan("be.groups")
@EnableJpaRepositories(basePackages = arrayOf("be.groups"))
@SpringBootTest(classes = arrayOf(DatabaseComponent::class))
@RunWith(SpringJUnit4ClassRunner::class)
class CodeListRepositoryTest {
@Autowired
lateinit var repository: CodeListRepository
@Test
fun findCodeListLikeCB() {
val codeLists = repository.findCodeListLikeCB(mapOf("codelistId" to "CANAL"))
assertNotNull(codeLists)
assertFalse(codeLists.isEmpty())
val codeList = repository.findCodeListLikeCB(mapOf("codelistId" to "CANAL", "numberValue" to 0))
assertNotNull(codeList)
assertFalse(codeList.isEmpty())
assertEquals(codeList.size, 1)
assertEquals(codeList[0].codelistId, "CANAL")
assertEquals(codeList[0].numberValue, 0)
}
}
测试配置(Mockito-Extensions/org.mockito.plugins.mockmaker)
mock-maker-inline
自2.0.0-m3以来出了什么问题?
有同样的问题。删除除默认NO-ARG构造函数外的所有实体类的构造函数。解决问题
自2.0.0-m5
您可以找到有用的Kotlin编译器插件。对于这种情况(或类似),我建议使用JPA编译器插件。它将为@entity,@embeddable和@mappedsuperclass自动自动生成默认的no-args构造函数,以自动提供@Entity,@embeddable和@mappedsuperclass,这将使Kotlin Reflection API能够正确创建和填充例如实体,而无需提供每个单个字段。
我添加了kotlin-反射依赖性,这对我有用。
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>