【问题标题】:Mapped foreign key in Hibernate Entity休眠实体中的映射外键
【发布时间】:2014-11-07 13:40:10
【问题描述】:

您好,使用 Spring Security 编写 Spring 应用程序。这是我的用户和帐户角色数据库:

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

我的实体类:

@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:从 user_roles 中选择 userrolese0_.username 作为 username3_1_0_,userrolese0_.id 作为 id1_0_0_,userrolese0_.id 作为 id1_0_1_,userrolese0_.name 作为 name2_0_1_,userrolese0_.username 作为 username3_0_1_ from user_roles userrolese0_ where userrolese0_.username=? 警告:org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:1722,SQLState:42000 错误:org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ORA-01722:无效编号

我的班级实现了 UserDetailsS​​ervice:

    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 Userreturn 从表中返回用户,但是当我尝试获取 user_roles 时出现上述错误。请检查我映射的正确性。我使用 Oracle 数据库和 Hiberante。

【问题讨论】:

  • 你是按用户名映射的?

标签: java spring oracle hibernate


【解决方案1】:

问题是,当您映射实体时,Hibernate 期望外键是被引用实体的 id,即您应该映射到 user-id 而不是用户名。

您的实体映射也似乎是错误的:您使用了目标实体为User 的ManyToOne,但属性的类型为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 始终是唯一使用@Id 注释的属性,那么这没问题,但如果您更改它,您可能会遇到查询选择错误数据甚至失败的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 2019-12-03
    • 2020-12-18
    • 2018-06-12
    • 1970-01-01
    相关资源
    最近更新 更多