JPA:BeanCreationException:OneToMany和ManyToOne映射JPA / Hibernate

14

我有两个带有外键关系的表。我尝试搜索如何做到这一点,但总是导致OneToMany和ManyToOne映射。我有这两个表。

user_role

enter image description here

用户

enter image description here

我正在尝试显示所有用户并通过获取用户角色表中位置列的值来显示他们的职位。

这些是我的类

User.java

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    ..........

    private UserRole userRole;

    @ManyToOne()
    @JoinColumn(name="role_id")
    public UserRole getUserRole() {
        return userRole;
    }

    public void setUserRole(UserRole userRole) {
        this.userRole = userRole;
    }

    .......
}

UserRole.java

@Entity
@Table(name="user_role")
public class UserRole {

    .......

    private List<User> user;

    @OneToMany(targetEntity=User.class, mappedBy="userRole",cascade=CascadeType.ALL, fetch = FetchType.LAZY)
    public List<User> getUser() {
        return user;
    }

    public void setUser(List<User> user) {
        this.user = user;
    }

    public long getRole_id() {
        return role_id;
    }

    public void setRole_id(long role_id) {
        this.role_id = role_id;
    }

    .........

}

我一直收到这个错误。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.List, at table: user_role, for columns: [org.hibernate.mapping.Column(user)]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:859) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at com.rtc_insurance.AdminApplication.main(AdminApplication.java:10) [classes/:na]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.List, at table: user_role, for columns: [org.hibernate.mapping.Column(user)]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:402) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    ... 16 common frames omitted
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, at table: user_role, for columns: [org.hibernate.mapping.Column(user)]
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:456) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:423) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.mapping.Property.isValid(Property.java:226) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:461) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    ... 20 common frames omitted

这是我第一次使用Spring,所以我并不太熟悉。任何帮助将不胜感激。


6个回答

14

你可以将关系移动到相关对象,就像这样

@ManyToOne()
@JoinColumn(name="role_id", referencedColumnName = "role_id", insertable = false, updatable = false)    
private UserRole userRole;

对于userRole也做同样的操作

@OneToMany(targetEntity=User.class, mappedBy="userRole",cascade=CascadeType.ALL, fetch = FetchType.LAZY)    
private List<User> user = new ArrayList<>();

更新

该jar文件似乎已损坏。尝试从.m2\repository中删除内容并执行mvn clean install

或者

右键单击您的项目,选择Maven,更新项目,勾选 强制更新快照/发布 版本。


我尝试过了,它仍然给我相同的错误。我还将列名位置更改为 role_id。:( - trumanblack1025
你能在你的application.properties中设置spring.jpa.generate.ddl-auto=create,让它为你创建表,然后告诉我是否仍然看到错误吗? - kj007
我尝试了,但是我使用了spring.jpa.hibernate.ddl-auto=create。它仍然给我相同的错误。抱歉,这是我第一次使用Spring。现在它给我这个错误。 - trumanblack1025
无法从类加载器层次结构中扫描[file:/C:/Users/roxan/.m2/repository/org/apache/maven/maven-project/2.2.1/maven-project-2.2.1.jar]。java.util.zip.ZipException: 无效的LOC头(错误的签名) 在java.util.zip.ZipFile.read(Native Method)~ [na:1.8.0_181] 在java.util.zip.ZipFile.access $ 1400(ZipFile.java:60)~ [na:1.8.0_181] - trumanblack1025
删除 .m2\repository 文件夹,然后运行 mvn clean install。 - kj007
显示剩余6条评论

3

提示一下,检查您的实体类并确保在类声明语句之前包含了@Entity注释。

@Entity
public class MyEntityClass{
 //code
}

然后在任何其他使用上面的MyEntityClass的@ManyToMany或@OneToMany关系的实体类中添加以下内容。

@OneToMany(mappedBy="mappingItem", cascade=CascadeType.ALL, orphanRemoval=true)
@JsonIgnore
private List<MyEntityClass> myEntityClassItemList;

这种方法在某种程度上对我奏效了,也许它会有所帮助。


2
你需要注释Java字段而不是getter,例如:
@OneToMany(targetEntity=User.class, mappedBy="userRole",cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private List<User> user;

并且针对 User.class

@ManyToOne
@JoinColumn(name="role_id")
private UserRole userRole;

此外,您是否在user表中定义了role_id列?从屏幕截图中我没有看到它。


我尝试过并将列从position重命名为role_id。"无法从类加载器层次结构中扫描[file:/C:/Users/roxan/.m2/repository/org/apache/maven/maven-project/2.2.1/maven-project-2.2.1.jar]" - trumanblack1025

2

我可以通过在字段和属性之间混合我的注释映射来重新创建您的异常。从您上面描述的问题中,我发现您注释了字段Id,但是注释了属性userRole,如果我也这样做,我会得到相同的错误。 我可以通过仅注释属性或字段来修复错误。 这两个模型都可以工作:

@Entity
@Table(name = "USER")
public class User {


private Long id;
private UserRole userRole;
String userName;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
    return id;
}


public void setId(Long id) {
    this.id = id;
}

@Column(name = "USER_NAME")
public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

@ManyToOne()
@JoinColumn(name="role_id")
public UserRole getUserRole() {
    return userRole;
}

public void setUserRole(UserRole userRole) {
    this.userRole = userRole;
}
}

这也可以运行:
@Entity
@Table(name = "USER")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@ManyToOne()
@JoinColumn(name="role_id")
private UserRole userRole;


@Column(name = "USER_NAME")
String userName;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

public UserRole getUserRole() {
    return userRole;
}

public void setUserRole(UserRole userRole) {
    this.userRole = userRole;
}
}

另一个模型对象注释字段的示例

@Entity
@Table(name = "USER")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@ManyToOne()
@JoinColumn(name="role_id")
private UserRole userRole;


@Column(name = "USER_NAME")
String userName;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

public UserRole getUserRole() {
    return userRole;
}

public void setUserRole(UserRole userRole) {
    this.userRole = userRole;
}
}

测试代码(我添加了这个因为经常会有人混淆,认为必须设置双向关系才能使用户和用户角色在保存到用户角色时都持久化)。

    List<User> users = new ArrayList<>();

    User user1 = new User();
    user1.setUserName("user1");
    users.add(user1);

    User user2 = new User();
    user2.setUserName("user2");
    users.add(user2);

    UserRole userRole = new UserRole();
    userRole.setRoleName("admin");
    //Unidirectional relationship
    user1.setUserRole(userRole);
    user2.setUserRole(userRole);
    //set Bidirectional relationship
    userRole.setUsers(users);

    userRole = userRoleRepository.save(userRole);

    //Show that the two users and the UserRole persisted
    UserRole result = userRoleRepository.findById(userRole.getId()).get();
    assertEquals(2, result.getUsers().size());

1
我简直不敢相信,但这对我起作用了。谢谢。 - akelec

0

创建和映射用户及其角色的简单方法。 定义两个实体类以及它们之间的关系,将会创建第三个映射表:

1. 角色实体类:

    @Entity
    @Table(name = "ROLE")
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Role {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long uuid;
        .
        .
        .
        
    }

2. 用户实体:

 @Entity
 @Table(name = "USER")
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long uuid;
    .
    .
    .
    @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
        @JoinTable(name="user_roles",
            joinColumns = {@JoinColumn(name="user_id", referencedColumnName="id")},
            inverseJoinColumns = {@JoinColumn(name="role_id", referencedColumnName="id")}
        )
    private List<Role> roles;
    
    
}

以上代码生成了三个表格:
  1. ROLE 2. USER 3. USER_ROLE

0

你可以像这样编写一对多关系: 职位 - 外键

public class UserRole {
.....
@OneToMany(targetEntity = User.class,cascade =CascadeType.ALL)
@JoinColumn(name="position",referencedColumnName = "role_id")
private List<User> users; 
......  
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接