2017-04-20 7 views
2

私は簡単なスプリングブートアプリケーションを書いています。なぜSpringブートが "ロールのコレクションを遅延して初期化できませんでした"がEagerフェッチタイプで解決されるのはなぜですか?

認証部分については、カスタムUserDetailsを実装しています。私はManyToMany注釈にフェッチタイプEagerを作るとき

Authentication Failed: failed to lazily initialize a collection of role: com.boot.cut_costs.config.security.CustomUserDetails.roles, could not initialize proxy - no Session

CustomUserDetails.java

@Entity 
@Table(name="ACCOUNT_USER") 
public class CustomUserDetails implements UserDetails { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "USER_ID") 
    private long id; 

    @NotBlank 
    @Column(name = "USERNAME") 
    private String username; 

    @NotBlank 
    @Column(name = "PASSWORD") 
    private String password; 

    @Column(name = "LOCKED") 
    private boolean locked; 

    @ManyToMany(cascade=CascadeType.ALL) 
    @JoinTable(name = "USER_ROLE", 
       joinColumns = @JoinColumn(name = "USER_ID"), 
       inverseJoinColumns = @JoinColumn(name = "ROLE_ID")) 
    private Set<CustomRole> roles; 

    public CustomUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) { // jpa only 
     this.setUsername(username); 
     this.setPassword(password); 
     this.roles = new HashSet<CustomRole>(); 
     for (GrantedAuthority authority: authorities) { 
      roles.add(new CustomRole(authority.getAuthority())); 
     } 
    } 

    public CustomUserDetails() { // jpa only 
    } 

    @Override 
    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    @Override 
    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public Set<CustomRole> getRoles() { 
     return roles; 
    } 

    public void setRoles(Set<CustomRole> roles) { 
     this.roles = roles; 
    } 

    @Override 
    public Collection<GrantedAuthority> getAuthorities() { 
     ArrayList<String> authoritiesList = new ArrayList<String>(); 
     for (CustomRole role: roles) { 
      authoritiesList.add(role.getRole()); 
     } 
     return AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", authoritiesList)); 
    } 
    //Some more getters and setters ... 

} 

CustomRole.java

@Entity 
@Table(name="ACCOUNT_ROLE") 
public class CustomRole { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="ROLE_ID") 
    private long id; 

    @Column(name="ROLE") 
    private String role; 

    public long getId() { 
     return id; 
    } 

    //delete if not necessary 
    public void setId(long id) { 
     this.id = id; 
    } 

    public String getRole() { 
     return role; 
    } 

    public void setRole(String role) { 
     this.role = role; 
    } 

    public CustomRole() {} //for jpa 

    public CustomRole(String role) { 
     this.role = role; 
    } 
} 

、:私は、ログインエンドポイントに要求を行うとき、私はこの例外を取得しますできます。

これは良いことではありません。まず、理由を知りたいのですが?第二に、私は良い習慣が何かを知りたいですか?サービス層とDAOをここに混ぜていますか?

+0

私はたぶん何か間違っていると言います私はあなたにアクセスしようとする前にトランザクションを終了すると思います怠惰なコレクション、それをロードせずに。 eagerモードは明らかにそれを修正しますが、もっと賢明な方法は、サービスメソッドが同じトランザクションでコレクションをロードして、遅延した動作をして、必要なときにサービスを介してコレクションを引き出すことです。 –

答えて

2

あなたはレイジーを使用するときは、役割と役割を持たないユーザをロードするには、あなたがここに

を使用する場合にのみ、あなたは春のセキュリティを使用して、あなたがCustomUserDetailsを呼び出すときにすべてのロールをロードするために熱心を置くべき支払いいただきます、 あなたがそれらを必要としない多くの詳細を読み込むので、一般的なケースでEagerを使用することは良い習慣ではありません

+0

Eagerフェッチタイプを使用する方が良い解決法はありますか?例えばデザインを変えることによって? –

+0

あなたはここで使うことができますあなたは大きな役割を担っていないので、問題なくEagerを使うことができますので、私はこのEagerを使っています。 @JoinTable(名= "user_roles"、 \t \t joinColumns = {@JoinColumn(名= "USER_ID"、referencedColumnNameとは= "ID")} = {@JoinColumn(名= "ROLE_ID" \t \t inverseJoinColumns、referencedColumnNameと=」 id ")} \t) \tプライベートリストロール;' –

関連する問題