【问题标题】:Why does @JoinColumn with POJO throw IllegalStateException为什么@JoinColumn 与 POJO 会抛出 IllegalStateException
【发布时间】:2021-07-19 12:53:15
【问题描述】:

启动 Spring Boot 应用程序时出现错误:java.lang.IllegalStateException: Expected to be able to resolve a type but got null! This usually stems from types implementing raw Map or Collection interfaces!

我通过sql查询创建了两个表:

create table experiment_results
(
    id int8 not null,
    model jsonb,
    train_errors jsonb,
    test_errors jsonb,
    prediction_error float8,
    prediction_result jsonb,
    prediction_report_file text,
    creation_date timestamp NOT NULL,
    PRIMARY KEY (id)
);

create table experiments
(
    id int8 not null,
    name text not null,
    normalized_file text,
    normalization_method varchar(255),
    normalization_statistic jsonb,
    neat_settings jsonb,
    columns jsonb,
    prediction_window_size int4,
    prediction_period int4,
    fk_project_id int8 not null,
    creation_date timestamp not null,
    updated_date timestamp not null,
    train_end_index int4,
    test_end_index int4,
    fk_experiment_result_id int8,
    PRIMARY KEY (id)
);

ALTER TABLE if EXISTS experiments add CONSTRAINT project_experiment_fk FOREIGN KEY(fk_project_id) references projects;
ALTER TABLE if EXISTS experiments add CONSTRAINT experiment_reuslt_fk FOREIGN KEY (fk_experiment_result_id) references experiment_results;

之后我为他们创建了两个 POJO 类:

实验结果:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "experiment_results", schema = "public")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id"
)
public class ExperimentResult {

    @Id
    @SequenceGenerator(name = "EXPERIMENT_RESULT_ID_GEN", sequenceName = "experiment_result_id_sequence", allocationSize = 1, schema = "public")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EXPERIMENT_RESULT_ID_GEN")
    @Column(name = "id")
    private Long id;


    @Basic
    @Column(name = "model", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    private Map model;


    @Column(name = "train_errors", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    private List<Map<String, Object>> trainErrors;


    @Column(name = "test_errors", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    private List<Map<String, Object>> testErrors;

    @Basic
    @Column(name = "prediction_error")
    private Double predictionError;

    @Basic
    @Column(name = "creation_date", nullable = false)
    private LocalDateTime creationDate;

    @Basic
    @Column(name = "prediction_reporAt_file")
    private String predictionReportFile;

}

实验:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "experiments", schema = "public")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id"
)
public class Experiment {

    @Id
    @SequenceGenerator(name = "EXPERIMENT_ID_GEN", sequenceName = "experiment_id_sequence", allocationSize = 1, schema = "public")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EXPERIMENT_ID_GEN")
    @Column(name = "id")
    @JsonView(ExperimentView.Id.class)
    private Long id;

    @Basic
    @Column(name = "name")
    @JsonView(ExperimentView.Info.class)
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_project_id", referencedColumnName = "id", nullable = false)
    @JsonIgnore
    private Project project;

    @Basic
    @Column(name = "normalized_file")
    @JsonIgnore
    private String normalizedDataFile;

    @Basic
    @Column(name = "normalization_method")
    @JsonView(ExperimentView.FullInfo.class)
    private String normalizationMethod;

    @Basic
    @Column(name = "normalization_statistic", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    @JsonView(ExperimentView.FullInfo.class)
    private Map<String, Object> normalization_statistic;

    @Basic
    @Column(name = "neat_settings", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    @JsonView(ExperimentView.FullInfo.class)
    private List<Map<String, Object>> neatSettings;

    @Basic
    @Column(name = "columns", columnDefinition = "jsonb")
    @Type(type = "jsonb")
    @JsonView(ExperimentView.FullInfo.class)
    private List<Map<String, Object>> columns;

    @Basic
    @Column(name = "prediction_window_size")
    @JsonView(ExperimentView.FullInfo.class)
    private Short predictionWindowSize;

    @Basic
    @Column(name = "prediction_period")
    @JsonView(ExperimentView.FullInfo.class)
    private Short predictionPeriod;

    @Basic
    @Column(name = "creation_date", nullable = false)
    @JsonView(ExperimentView.Info.class)
    private LocalDateTime creationDate;

    @Basic
    @Column(name = "updated_date", nullable = false)
    @JsonView(ExperimentView.Info.class)
    private LocalDateTime updatedDate;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "fk_experiment_result_id", referencedColumnName = "id")
    private ExperimentResult experimentResult;

}

当应用程序启动时,它因堆栈跟踪而失败:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'experimentRepository' defined in ru.filippov.neat.repository.ExperimentRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Expected to be able to resolve a type but got null! This usually stems from types implementing raw Map or Collection interfaces!
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1794) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$209/0000000000000000.getObject(Unknown Source) ~[na:na]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:624) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:612) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.data.repository.config.DeferredRepositoryInitializationListener.onApplicationEvent(DeferredRepositoryInitializationListener.java:51) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.repository.config.DeferredRepositoryInitializationListener.onApplicationEvent(DeferredRepositoryInitializationListener.java:36) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:898) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at ru.filippov.neat.NeatvueApplication.main(NeatvueApplication.java:11) ~[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:49) ~[spring-boot-devtools-2.3.4.RELEASE.jar:2.3.4.RELEASE]
Caused by: java.lang.IllegalStateException: Expected to be able to resolve a type but got null! This usually stems from types implementing raw Map or Collection interfaces!
    at org.springframework.data.util.TypeInformation.getRequiredActualType(TypeInformation.java:184) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.model.AbstractPersistentProperty.getActualType(AbstractPersistentProperty.java:286) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl.getActualType(JpaPersistentPropertyImpl.java:120) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl.lambda$new$3(JpaPersistentPropertyImpl.java:111) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl$$Lambda$718/0000000000000000.get(Unknown Source) ~[na:na]
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:212) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl.isEntity(JpaPersistentPropertyImpl.java:150) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.model.AbstractPersistentProperty.getPersistentEntityTypes(AbstractPersistentProperty.java:150) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl.getPersistentEntityTypes(JpaPersistentPropertyImpl.java:132) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:562) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:520) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:705) ~[spring-core-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:389) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator$$Lambda$723/0000000000000000.accept(Unknown Source) ~[na:na]
    at java.base/java.util.Collections$SingletonSet.forEach(Collections.java:4797) ~[na:na]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:562) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:520) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:705) ~[spring-core-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:389) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:263) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:206) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:90) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$4(RepositoryFactoryBeanSupport.java:295) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport$$Lambda$663/0000000000000000.accept(Unknown Source) ~[na:na]
    at java.base/java.util.Optional.ifPresent(Optional.java:183) ~[na:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:295) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1790) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    ... 31 common frames omitted

之后我从Experiment POJO 中删除了ExperimentResult 字段,我的应用程序成功启动。我做错了什么?例如,fk_project_id 工作正常,但它有 @ManyToOne 注释。

【问题讨论】:

    标签: spring spring-boot hibernate spring-data


    【解决方案1】:

    Hibernate 不直接支持 JSONB。

    你必须使用转换器。

    Hibernate Types 项目中有一个转换器集合:https://github.com/vladmihalcea/hibernate-types

    【讨论】:

    • 我的 Maven 中有休眠类型的依赖项。问题的原因不是依赖。正如我所说,当我删除:@OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "fk_experiment_result_id", referencedColumnName = "id") private ExperimentResult experimentResult; from Experiment POJO - 应用程序运行成功
    • 我使用@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)注解在Hibernate Types中定义转换器
    【解决方案2】:

    问题是private Map model; in ExperimentResult POJO。

    我们必须定义泛型,例如Map&lt;String, Object&gt; model

    【讨论】:

      猜你喜欢
      • 2019-11-23
      • 2011-07-07
      • 2012-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-28
      • 2018-07-22
      • 2021-12-20
      相关资源
      最近更新 更多