Java 通过@EmbeddedID上的永久属性[model.Credentials#email]的反射访问字段时出错

Java 通过@EmbeddedID上的永久属性[model.Credentials#email]的反射访问字段时出错,java,spring-boot,hibernate,spring-security,spring-data-jpa,Java,Spring Boot,Hibernate,Spring Security,Spring Data Jpa,在我的spring boot应用程序上实现权限时,我遇到了一些问题,在深入研究之后,我意识到我的凭证和权限表之间的关联可能是错误的 事实上,我注意到Spring允许每种类型的用户(不管他们的权限)访问任何方法,即使是我认为安全的方法。在这一点上,我实现了一个.findAll()方法来实际查看关联上是否存在某种问题,确实存在 让我首先展示MySQL表: CREATE TABLE credentials ( credential_id bigint UNSIGNED PRIMARY KEY AU

在我的spring boot应用程序上实现
权限
时,我遇到了一些问题,在深入研究之后,我意识到我的
凭证
权限
表之间的关联可能是错误的

事实上,我注意到Spring允许每种类型的用户(不管他们的权限)访问任何方法,即使是我认为安全的方法。在这一点上,我实现了一个
.findAll()
方法来实际查看关联上是否存在某种问题,确实存在

让我首先展示MySQL表:

CREATE TABLE credentials (
  credential_id bigint UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  email varchar(50) NOT NULL UNIQUE,
  password varchar(255) NOT NULL,
  enabled BOOLEAN NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


CREATE TABLE authorities (
  email varchar(50) NOT NULL,
  authority varchar(50) NOT NULL,
  PRIMARY KEY (email, authority),
  CONSTRAINT fk_authorities_credentials FOREIGN KEY(email) REFERENCES credentials(email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
在跳转到实体中的关联之前,值得注意的是,authorities实体具有和嵌入了反映表设计的键。因此,
电子邮件
列既是一个
外键
,同时也是一个主键:

@Embeddable
public class AuthoritiesKey implements Serializable {
  @OneToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "email", nullable = false
          ,referencedColumnName = "email")
  private Credentials credentials;

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

//getters setters omitted
}
证书类别:

@Entity
@Table(name = "credentials")
public class Credentials implements Serializable {

  @OneToOne(cascade = CascadeType.ALL,
          fetch = FetchType.LAZY,
          mappedBy = "ak.credentials")
  private Authorities authorities;

//other fields and getters/setters omitted
}
删除双边关联(因此只将其保留在AuthoritiesKey类上),hibernate将成功返回所有凭据(当然没有它们的权限)和所有权限(这次是在凭据之前)

我不能把我的头绕在它周围

当我离开双边关联时,我得到的完整有意义的堆栈跟踪如下:

Error accessing field [private java.lang.String com.server.model.Credentials.email] by reflection for persistent property [com.servermodel.Credentials#email] : 64; 
nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.String com.server.model.Credentials.email] by reflection for persistent property [com.server.model.Credentials#email] : 64
其中64是
凭证
表中(最后一个但被调用的第一个)行的id

==更新===

public class CredentialsService implements UserDetailsService {

  @Autowired
  private CredentialsRepository cr;

   @Override
  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
    Credentials user = cr.findByEmail(email);
    if (user == null){
      throw new UsernameNotFoundException(email);
    }
    return new UserPrincipal(user);
  }
}

由于hibernate错误,您似乎无法在此处使用
@OneToOne
。(请参阅)即使在Hibernate 5.4.28.Final中也可以复制

作为解决方法,我建议您通过以下方式更正映射:

@实体
@表(name=“当局”)
公共阶级权威{
@嵌入ID
私钥pk;
// ...
}
@可嵌入
公共类AuthoritiesKey实现可序列化{
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“email”,referencedColumnName=“email”,nullable=false)
私人证书;
@列(name=“authority”,nullable=false)
私人字符串管理机构;
公共权限密钥(凭据、字符串权限){
this.credentials=凭证;
这个。权威=权威;
}
公共权威密钥(){
}
//省略getters setters
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(o==null | | getClass()!=o.getClass())返回false;
AuthoritiesKey pk=(AuthoritiesKey)o;
返回Objects.equals(凭证,pk.credentials)&&
Objects.equals(authority,pk.authority);
}
@凌驾
公共int hashCode(){
返回Objects.hash(凭证、权限);
}
}
@实体
@表(name=“凭证”)
公共类凭据实现可序列化{
@身份证
@列(name=“凭证id”)
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@OneToMany(级联=级联类型.ALL,
fetch=FetchType.LAZY,
mappedBy=“pk.credentials”)
私人名单管理机构;
@归化
@列(name=“email”)
私人字符串电子邮件;
@短暂的
公共当局
{
返回this.authorities!=null&&this.authorities.size()>0
?this.authorities.get(0):null;
}
// ...
}

谢谢你,斯特恩,尝试过了,没有用。我还修改了AuthorityRepository接口如下:公共接口AuthorityRepository扩展了JpaRepository(替换ID)能否显示您获得的堆栈跟踪。我用完整的堆栈跟踪更新了问题,谢谢。请出示
CredentialsService.loadUserByUsername
方法。查看更新的答案。