web-dev-qa-db-fra.com

OneToMany & ManyToOne cartographie Spring Boot / Hibernate

J'ai deux tables avec des relations clés étrangères. J'ai essayé de chercher comment le faire et cela mène toujours à la cartographie OneToMany & ManyToOne. J'ai ces deux tableaux.

rôle d'utilisateur

enter image description here

utilisateur

enter image description here

J'essaie d'afficher tous les utilisateurs et d'afficher leur position en obtenant la valeur de la colonne de position dans la table user_role.

Ce sont mes cours

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;
    }

    .........

}

Et je continue à recevoir cette erreur.

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

C'est la première fois que j'utilise le printemps, donc je ne suis pas très familier. Toute aide serait grandement appréciée.

2
trumanblack1025

Pouvez-vous déplacer la relation vers un objet connexe comme celui-ci

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

et faire de même pour userRole

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

Mise à jour

Le fichier jar semble corrompu. Essayez de supprimer le contenu du référentiel .m2\et mvn clean install

OR

Cliquez ensuite avec le bouton droit sur votre projet, sélectionnez Maven, Mettre à jour le projet, cochez Forcer la mise à jour des instantanés/versions.

1
kj007

Je peux recréer votre exception en mélangeant mon mappage d'annotations entre les champs et les propriétés. Je vois dans le problème que vous avez décrit ci-dessus que vous annotez l'ID de champ, mais annotez ensuite la propriété userRole, si je fais la même chose, j'obtiens la même erreur. Je peux corriger l'erreur en annotant uniquement les propriétés ou les champs. Ces deux modèles fonctionnent:

@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;
}
}

Cela fonctionne également:

@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;
}
}

Exemple de l'autre objet modèle annotant les champs

@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;
}
}

Code de test (j'ai ajouté cela car il y a souvent confusion qu'il faut définir la relation bidirectionnelle pour que les utilisateurs et userRole persistent avec une sauvegarde sur 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
Stephen

Juste un indice, vérifiez vos classes d'entités et assurez-vous d'avoir inclus l'annotation @Entity juste avant l'instruction de déclaration de classe.

@Entity
public class MyEntityClass{
 //code
}

Ensuite, sur toute autre classe d'entité qui utilise MyEntityClass ci-dessus sous la relation @ManyToMany ou @OneToMany, ajoutez ce qui suit.

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

Cette approche a fonctionné pour moi, peut-être que cela pourrait aider.

1
briancollins081

Vous devez annoter les champs Java pas le getter comme:

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

et pour User.class

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

De plus, avez-vous défini le role_id colonne dans la table user? Je ne peux pas voir cela sur la capture d'écran

0
rieckpil