JPA实体关联配置错误:EntityManagerFactory初始化失败求助
工单系统JPA关联错误修复方案
我正在为公司开发管理系统的工单模块,之前使用NoSQL数据库,现在转用SQL数据库,需要实现用户创建工单并添加评论的功能,但系统启动时无法初始化JPA EntityManagerFactory,报错信息及相关实体类代码如下:
相关实体类代码
User.java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // identyfikator @Column(nullable = false) private String firstName; @Column(nullable = false) private String lastName; @Column(nullable = false) private String jobPosition; @Column(nullable = false) private String department; @Column(nullable = false) private String shortDep; @Column(nullable = false) private String email; @Column(nullable = true) private String deskNumber; @Column(nullable = true) private String mobileNumber; @Column(nullable = true) private boolean isPrivate; @Column(nullable = false) private String password; @ManyToOne @JsonManagedReference private List<Comment> comments; @JsonIgnore private Session session; ... }
Ticket.java
@Entity public class Ticket { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private User owner; @Column private DateTime postedTime; @Column private String text; @ManyToOne private User assignedUser; @ManyToOne @JsonManagedReference private List<Comment> comments; ... }
Comment.java
@Entity public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne @JsonManagedReference private User owner; @OneToMany @JoinColumn(name = "ticketId") private Ticket ticket; @Column private String text; ... }
Session.java
@Entity public class Session { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne @JsonManagedReference private User user; @Column private DateTime expTime; }
错误日志
ERROR 1 --- [ticket_sys_backend] [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Property 'com.Comment.ticket' is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection' ticket_sys | 2024-12-23T09:54:07.826Z WARN 1 --- [ticket_sys_backend] [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Property 'com.Comment.ticket' is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection' ticket_sys | 2024-12-23T09:54:07.826Z INFO 1 --- [ticket_sys_backend] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... ticket_sys | 2024-12-23T09:54:07.862Z INFO 1 --- [ticket_sys_backend] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. ticket_sys | 2024-12-23T09:54:07.864Z INFO 1 --- [ticket_sys_backend] [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] ticket_sys | 2024-12-23T09:54:07.871Z INFO 1 --- [ticket_sys_backend] [ main] .s.b.a.l.ConditionEvaluationReportLogger : ticket_sys | ticket_sys | Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. ticket_sys | 2024-12-23T09:54:07.879Z ERROR 1 --- [ticket_sys_backend] [ main] o.s.boot.SpringApplication : Application run failed ticket_sys | ticket_sys | org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Property 'com.Comment.ticket' is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection' ticket_sys | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:970) ~[spring-context-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) ~[spring-context-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.0.jar!/:3.4.0] ticket_sys | at sz.backend.System_zgloszen_backend.SystemZgloszenBackendApplication.main(SystemZgloszenBackendApplication.java:10) ~[!/:0.0.1-SNAPSHOT] ticket_sys | at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] ticket_sys | at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] ticket_sys | at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) ~[zgloszenia.jar:0.0.1-SNAPSHOT] ticket_sys | at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) ~[zgloszenia.jar:0.0.1-SNAPSHOT] ticket_sys | at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40) ~[zgloszenia.jar:0.0.1-SNAPSHOT] ticket_sys | Caused by: org.hibernate.AnnotationException: Property 'com.Comment.ticket' is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection' ticket_sys | at org.hibernate.boot.model.internal.CollectionBinder.determineSemanticJavaType(CollectionBinder.java:1121) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.CollectionBinder.determineCollectionClassification(CollectionBinder.java:1013) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.CollectionBinder.createBinderAutomatically(CollectionBinder.java:855) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.CollectionBinder.getCollectionBinder(CollectionBinder.java:848) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.CollectionBinder.bindCollection(CollectionBinder.java:284) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.PropertyBinder.bindProperty(PropertyBinder.java:897) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.PropertyBinder.buildProperty(PropertyBinder.java:811) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations(PropertyBinder.java:732) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.EntityBinder.processIdPropertiesIfNotAlready(EntityBinder.java:1086) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.EntityBinder.handleIdentifier(EntityBinder.java:418) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.EntityBinder.bindEntityClass(EntityBinder.java:250) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.internal.AnnotationBinder.bindClass(AnnotationBinder.java:401) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:257) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:281) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:324) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) ~[hibernate-core-6.6.2.Final.jar!/:6.6.2.Final] ticket_sys | at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[spring-orm-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:419) ~[spring-orm-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:400) ~[spring-orm-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798) ~[spring-beans-6.2.0.jar!/:6.2.0] ticket_sys | ... 20 common frames omitted
错误原因分析
核心错误是Comment.ticket字段使用了@OneToMany注解,但该字段是单个Ticket对象而非集合类型,注解与字段类型不匹配。此外其他实体类也存在关联注解使用错误:
- User类的
comments是集合,却用了@ManyToOne(应为@OneToMany) - Ticket类的
comments是集合,却用了@ManyToOne(应为@OneToMany) - Session与User的双向
@OneToOne关联缺少mappedBy配置
修正后的实体类代码
User.java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // identyfikator @Column(nullable = false) private String firstName; @Column(nullable = false) private String lastName; @Column(nullable = false) private String jobPosition; @Column(nullable = false) private String department; @Column(nullable = false) private String shortDep; @Column(nullable = false) private String email; @Column(nullable = true) private String deskNumber; @Column(nullable = true) private String mobileNumber; @Column(nullable = true) private boolean isPrivate; @Column(nullable = false) private String password; // 一个用户对应多个评论,mappedBy指定关联字段在Comment类中 @OneToMany(mappedBy = "owner") @JsonManagedReference private List<Comment> comments; // 双向OneToOne关联,mappedBy指定Session类中的关联字段 @OneToOne(mappedBy = "user") @JsonIgnore private Session session; ... }
Ticket.java
@Entity public class Ticket { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private User owner; @Column private DateTime postedTime; @Column private String text; @ManyToOne private User assignedUser; // 一个工单对应多个评论,mappedBy指定关联字段在Comment类中 @OneToMany(mappedBy = "ticket") @JsonManagedReference private List<Comment> comments; ... }
Comment.java
@Entity public class Comment { @Id
相关产品推荐
相关产品推荐

