Сопоставленный внешний ключ в Hibernate Entity

1

Привет, напишите приложение Spring, используя Spring Security. Это моя база данных для роли пользователя и учетной записи:

create table users (

  id int not null primary key,
  username varchar2(20) not null unique,
  password varchar2(20) not null,
  firstName varchar2(20),
  lastName varchar2(20),
  personalId varchar2(11) unique,
  city varchar2(40),
  address varchar2(40),
  email varchar2(30) unique,
  phone varchar2(9) unique,
  enabled number(1) not null
);

create table user_roles (
  id int primary key,
  name varchar2(20) not null,
  username varchar(20) constraint username_fk references users(username) not null
);

Классы My Entity:

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

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotNull
    @Column(name = "username")
    private String username;
    @NotNull
    @Column(name = "password")
    private String password;
    @Column(name = "firstName")
    private String firstName;
    @Column(name = "lastName")
    private String lastName;
    @Column(name = "personalId")
    private String personalId;
    @Column(name = "city")
    private String city;
    @Column(name = "address")
    private String address;
    @Column(name = "email")
    private String email;
    @Column(name = "phone")
    private String phone;
    @NotNull
    @Column(name = "enabled")
    private int enabled;
    @OneToMany(mappedBy = "username")
    private Set<UserRole> userRoleSet = new HashSet<UserRole>(0);

@Entity
@Table(name = "user_roles")
public class UserRole implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotNull
    @Column(name = "name")
    private String name;
    @JoinColumn(name = "username")
    @ManyToOne(targetEntity = User.class)
    private String username;

Когда я пытаюсь войти в систему, у меня есть ошибка:

Hibernate: выберите userrolese0_.username как username3_1_0_, userrolese0_.id как id1_0_0_, userrolese0_.id как id1_0_1_, userrolese0_.name как имя2_0_1_, userrolese0_.username как username3_0_1_ из user_roles userrolese0_, где userrolese0_.username =? WARN: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Ошибка SQL: 1722, SQLState: 42000 ОШИБКА: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ORA-01722: неверный номер

Мой класс реализует UserDetailsService:

    package pl.piotr.ibank.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.piotr.ibank.daointerface.UserDao;
import pl.piotr.ibank.model.UserRole;

@Transactional(readOnly = true)
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {

        pl.piotr.ibank.model.User user = userDao.findByUsername(username);

        List<GrantedAuthority> authorities = buildUserAuthority(user
                .getUserRole());

        return buildUserForAuthentication(user, authorities);

    }

    private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        for (UserRole userRole : userRoles) {
            setAuths.add(new SimpleGrantedAuthority(userRole.getName()));
        }

        List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(
                setAuths);
        return result;
    }

    private UserDetails buildUserForAuthentication(
            pl.piotr.ibank.model.User user, List<GrantedAuthority> authorities) {
        return new User(user.getUsername(), user.getPassword(), true, true,
                true, true, authorities);
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

Я так думаю, мой картографический ключ для таблиц плох. Пример запроса from User возвращающего пользователей из таблицы, но когда я пытаюсь получить user_roles, у меня выше ошибки. Проверьте правильность моих сопоставлений. Я использую базу данных Oracle и Hiberante.

  • 0
    Вы картируете по имени пользователя?
Теги:
spring
hibernate

1 ответ

1
Лучший ответ

Проблема заключается в том, что при отображении объектов Hibernate ожидает, что внешний ключ будет идентификатором объекта, на который ссылается, то есть вы должны сопоставить идентификатор пользователя вместо имени пользователя.

Также ваше сопоставление сущности кажется неправильным: вы используете ManyToOne с целевым объектом, являющимся User но тип свойства - String. AFAIK Hibernate попытается присвоить пользователю username, которое должно потерпеть неудачу.

Стол должен выглядеть так:

create table user_roles (
  id int primary key,
  name varchar2(20) not null,
  userid int constraint userid_fk references users(id) not null
);

И тогда отображение в UserRole должно быть:

@JoinColumn(name = "userid")
@ManyToOne
private User user;

Плюс обратное отображение в User:

@OneToMany(mappedBy = "user")
private Set<UserRole> userRoleSet;

В качестве примечания следует помнить, что id является специальным ключевым словом в HQL, то есть он всегда будет ссылаться на идентификатор объекта. Если id всегда является единственным свойством, аннотированным с @Id то это не проблема, но если вы измените это, вы можете столкнуться с проблемами с запросами, которые выбирают неправильные данные или даже сбой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню