2017-10-11 9 views
1

enter image description here Je suis en train de se joindre à trois tables avec mon modèle est class.Here mes classes de modèle, Users.javaComment utiliser Association OneToMany dans plus d'une table

@Entity 
@Table(name = "users") 
public class Users implements Serializable{ 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Integer id; 
public String username; 
public String password; 
public Integer privid; 

@OneToMany(cascade = CascadeType.ALL, mappedBy = "pid") 
private Set<Privillages> priviJoin; 

@OneToMany(cascade = CascadeType.ALL, mappedBy = "actid") 
private Set<Actions> actionJoin; 



public Integer getId() { 
    return id; 
} 

public void setId(Integer id) { 
    this.id = id; 
} 
@Column(name = "username") 
public String getUsername() { 
    return username; 
} 
public void setUsername(String username) { 
    this.username = username; 
} 
@Column(name = "password") 
public String getPassword() { 
    return password; 
} 
public void setPassword(String password) { 
    this.password = password; 
} 

@Column(name = "privid") 
public Integer getPrivid() { 
    return privid; 
} 
public void setPrivid(Integer privid) { 
    this.privid = privid; 
} 


public Set<Privillages> getPriviJoin() { 
    return priviJoin; 
} 

public void setPriviJoin(Set<Privillages> priviJoin) { 
    this.priviJoin = priviJoin; 
} 

public Set<Actions> getActionJoin() { 
    return actionJoin; 
} 

public void setActionJoin(Set<Actions> actionJoin) { 
    this.actionJoin = actionJoin; 
} 

public Users() { 
} 
} 

Et Privillages.java,

@Entity 
@Table(name = "privillages") 
public class Privillages implements Serializable { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
public Integer id; 

@Column(name = "pname") 
public String pname; 


@ManyToOne(optional = false) 
@JoinColumn(name = "pid", referencedColumnName = "privid") 
public Users pid; 

public Integer getId() { 
    return id; 
} 
public void setId(Integer id) { 
    this.id = id; 
} 


public String getPname() { 
    return pname; 
} 
public void setPname(String pname) { 
    this.pname = pname; 
} 

public Users getPid() { 
    return pid; 
} 
public void setPid(Users pid) { 
    this.pid = pid; 
} 

public Privillages(){ 
} 
} 

Et Actions.java

@Entity 
@Table(name = "actions") 
public class Actions implements Serializable { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
public Integer id; 


@Column(name = "actname") 
public String actname; 

@ManyToOne(optional = false) 
@JoinColumn(name = "actid", referencedColumnName = "privid") 
public Users actid; 



public Integer getId() { 
    return id; 
} 

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

public String getActname() { 
    return actname; 
} 

public void setActname(String actname) { 
    this.actname = actname; 
} 

public Users getActid() { 
    return actid; 
} 

public void setActid(Users actid) { 
    this.actid = actid; 
} 
public Actions(){ 
} 
} 

Mon référentiel contenant code suivant,

@Query(value = "SELECT u.*,p.*,a.* FROM users u " 
      + "INNER JOIN privillages p ON u.privid = p.pid " 
      + "INNER JOIN actions a ON u.privid = a.actid", 
nativeQuery=true) 
Set<Users> findByUsername(); 

Mon action du contrôleur est,

@RequestMapping(value = "/joinResult", method = RequestMethod.GET) 
    public ModelAndView joinResultShow(Model model) 
     { 
      model.addAttribute("joinData",userRepo.findByUsername()); 
      ModelAndView viewObj = new ModelAndView("fleethome"); 
      return viewObj; 
     } 

Et moi fleethome est comme,

<table> 
     <th> Username </th> 
     <th> Privillage </th> 
     <th> Action </th> 
      <tr th:each="message : ${joinData}"> 

       <td th:text="${message.username}"></td> 
       <td><span th:each="privi : ${message.priviJoin}" 
       th:text="${privi.pname}"></span></td> 
       <td><span th:each="action : ${message.actionJoin}" 
       th:text="${action.actname}"></span></td> 
      </tr> 
    </table> 

Je suis en train de rejoindre Privillages et Actions avec mes principaux utilisateurs du modèle. Utilisateurs-Privillages ont un à plusieurs. Et aussi Utilisateurs - Les actions ont aussi un à plusieurs. Lorsque j'ai rejoint les utilisateurs avec des privilèges, cela fonctionne bien. J'ai rejoint avec succès deux tables.

Maintenant, j'ai aussi besoin de rejoindre la classe Actions avec les utilisateurs. J'essaie d'afficher une colonne de chaque classe Model. Lorsque j'ai implémenté la procédure que j'ai suivie précédemment pour rejoindre Users-Privillages ne fonctionne pas ici, quand j'ai ajouté une table supplémentaire.

Je reçois l'erreur comme,

There was an unexpected error (type=Internal Server Error, status=500). 
Exception evaluating SpringEL expression: "message.pname" (fleethome:65) 

Quelqu'un peut-il me aider à rejoindre la table une supplémentaire avec ma précédente rejoindre. ??

Répondre

1

Vous ne pouvez probablement pas faire cela sans changements d'entité de modèle. Si je vous ai bien compris, vous voulez obtenir votre classe d'entité avec plusieurs collections connexes initialisées à partir de DB. Mais cela ne peut pas fonctionner comme c'est dans votre cas, car MultipleBagFetchException: cannot simultaneously fetch multiple bags. C'est fondamentalement le même problème de plusieurs collections avec fetch = FetchType.EAGER. Une solution facile serait de changer Collection<Privillages> à Set<Privillages> ou même pour Actions si vous le pouvez. More info


Quant à Exception evaluating SpringEL expression: "message.pid.username" la raison réelle est que vous essayez de travailler avec joinData comme si elle est une partie enregistrement de la table de base de données, mais vous devez travailler avec elle comme vous le feriez avec des classes java. Parce que vous avez déjà obtenu Set<User> joinData depuis Hibernate. Peut essayer quelque chose comme

<tr th:each="message : ${joinData}"> 

    <td th:text="${message.username}"></td> 
    <td><span th:each="privi : ${message.priviJoin}" 
       th:text="${privi.pname}"></span></td> 
    <td><span th:each="action : ${message.actionJoin}" 
       th:text="${action.actname}"></span></td> 

</tr> 

Si vous voulez même sortie comme dans l'image que vous avez fourni, vous pouvez essayer:

<div th:remove="tag" th:each="message : ${joinData}"> 
    <div th:remove="tag" th:each="privi : ${message.priviJoin}"> 
     <div th:remove="tag" th:each="action : ${message.actionJoin}"> 
      <tr> 
       <td th:text="${message.username}"></td> 
       <td th:text="${privi.pname}"></td> 
       <td th:text="${action.actname}"></td> 
      </tr> 
     </div> 
    </div> 
</div> 
+0

Ok, je vais explorer plus sur cette base. Je suis nouveau au printemps et au printemps données JPA, j'essaie de rejoindre plusieurs, comme vous l'avez déjà compris. Je vais lire plus sur cette collection, Set, Et va essayer sur ceux-ci. Et merci pour votre réponse monsieur. – Jacob

+0

J'ai essayé la même chose avec l'ensemble. Mais cette fois j'ai eu une erreur dans la page de vue que - "Il y avait une erreur inattendue (type = erreur interne de serveur, statut = 500) Exception évaluant l'expression de SpringEL:" message.pid.username "(fleethome: 52)".J'ai également édité ma question après ma mise à jour du code. Comment puis-je résoudre ce problème? Pouvez-vous regarder sur mon code et erreur si vous avez le temps ?? – Jacob

+0

@MJacob Essayez 'model.addAttribute (" joinData ", userRepo.findByUsername()); retourne "fleethome" 'au lieu de créer un nouveau modèle. Ou mettez 'viewObj.addAttribute (" joinData ", userRepo.findByUsername());' une ligne plus bas à la place. Je pense que vous devez définir 'joinData' sur le modèle' viewObj' vous renvoyer – varren