Как реализовать Spring Security User / Authorities с Hibernate / JPA2?

Я пытаюсь реализовать DAO для работы с аутентификацией базы данных Spring Security в Hibernate / JPA2. Spring использует следующие отношения и ассоциации для представления пользователя и ролей:

alt text

представлен как запрос postgresql create:

CREATE TABLE users
(
  username character varying(50) NOT NULL,
  "password" character varying(50) NOT NULL,
  enabled boolean NOT NULL,
  CONSTRAINT users_pkey PRIMARY KEY (username)
);
CREATE TABLE authorities
(
  username character varying(50) NOT NULL,
  authority character varying(50) NOT NULL,
  CONSTRAINT fk_authorities_users FOREIGN KEY (username)
      REFERENCES users (username) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

Использование встроенных реализаций GrantedAuthorities , UserDetailsService и UserDetailsmanager , все нормально. Тем не мение, Я не удовлетворен реализацией Spring JDBC и хотел бы написать свои собственные. Для этого я попытался создать представление отношений с помощью следующих бизнес-объектов:

Пользовательский объект:

@Entity
@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"username"})})
public class AppUser implements UserDetails, CredentialsContainer {

    private static final long serialVersionUID = -8275492272371421013L;

    @Id
    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @Column(name = "password", nullable = false)
    @NotNull
    private String password;

    @OneToMany(
            fetch = FetchType.EAGER, cascade = CascadeType.ALL,
            mappedBy = "appUser"
    )
    private Set<AppAuthority> appAuthorities;

    @Column(name = "accountNonExpired")
    private Boolean accountNonExpired;

    @Column(name = "accountNonLocked")
    private Boolean accountNonLocked;

    @Column(name = "credentialsNonExpired")
    private Boolean credentialsNonExpired;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "personalinformation_fk", nullable = true)
    @JsonIgnore
    private PersonalInformation personalInformation;

    @Column(name = "enabled", nullable = false)
    @NotNull
    private Boolean enabled;

    public AppUser(
            String username,
            String password,
            boolean enabled,
            boolean accountNonExpired,
            boolean credentialsNonExpired,
            boolean accountNonLocked,
            Collection<? extends AppAuthority> authorities,
            PersonalInformation personalInformation
    ) {
        if (((username == null) || "".equals(username)) || (password == null)) {
            throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
        }

        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.appAuthorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        this.personalInformation = personalInformation;
    }

    public AppUser() {
    }

    @JsonIgnore
    public PersonalInformation getPersonalInformation() {
        return personalInformation;
    }

    @JsonIgnore
    public void setPersonalInformation(PersonalInformation personalInformation) {
        this.personalInformation = personalInformation;
    }

    // Getters, setters 'n other stuff

И авторитетный объект как реализация GrantedAuthorities:

@Entity
@Table(name = "authorities", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class AppAuthority implements GrantedAuthority, Serializable {
    //~ Instance fields ================================================================================================

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "username", nullable = false)
    private String username;

    @Column(name = "authority", nullable = false)
    private String authority;

    // Here comes the buggy attribute. It is supposed to repesent the
    // association username<->username, but I just don't know how to
    // implement it 
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "appuser_fk")
    private AppUser appUser;

    //~ Constructors ===================================================================================================

    public AppAuthority(String username, String authority) {
        Assert.hasText(authority,
                "A granted authority textual representation is required");
        this.username = username;
        this.authority = authority;
    }

    public AppAuthority() {
    }

    // Getters 'n setters 'n other stuff

Моя проблема - @ManyToOne доц. of AppAuthorities : Предполагается, что это "имя пользователя", но попытка и выполнение этого вызовут ошибку, потому что мне нужно ввести этот атрибут как String ... в то время как Hibernate ожидает связанный объект. Итак, я попытался предоставить правильный объект и создать ассоциацию с помощью @JoinColumn (name = "appuser_fk") . Это, конечно, чушь, потому что, чтобы загрузить пользователя, У меня будет внешний ключ в имени пользователя , а Hibernate будет искать его в appuser_fk , который всегда будет пустым.

Итак, вот мой вопрос: любые предложения о том, как изменить вышеупомянутый код, чтобы получить правильную реализацию модели данных JPA2?

Спасибо

8
задан Ta Sas 12 September 2010 в 23:17
поделиться