java - 通过 @EmbeddedID 上的持久属性 [model.Credentials#email] 的反射访问字段时出错
问题描述
我Authorities
在我的 Spring Boot 应用程序上实施时遇到了问题,经过一番挖掘后,我意识到我Credentials
和Authorities
表之间的关联可能是错误的。
事实上,我注意到 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;
在跳转到实体中的关联之前,值得注意的是,权限实体具有反映表设计的嵌入键。因此,该email
列同时是 aforeign key
和主要的:
@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 Credential
。
=== 更新 ===
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);
}
}
解决方案
@OneToOne
由于休眠错误,您似乎无法在此处使用。(请参阅HHH-3824)即使使用 Hibernate 5.4.28.Final 也可以复制它
作为解决方法,我建议您以这种方式更正您的映射:
@Entity
@Table(name = "authorities")
public class Authorities {
@EmbeddedId
private AuthoritiesKey pk;
// ...
}
@Embeddable
public class AuthoritiesKey implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "email", referencedColumnName = "email", nullable = false)
private Credentials credentials;
@Column(name = "authority", nullable = false)
private String authority;
public AuthoritiesKey(Credentials credentials, String authority) {
this.credentials = credentials;
this.authority = authority;
}
public AuthoritiesKey() {
}
// getters setters omitted
@Override
public boolean equals(Object o) {
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
AuthoritiesKey pk = (AuthoritiesKey) o;
return Objects.equals( credentials, pk.credentials ) &&
Objects.equals( authority, pk.authority );
}
@Override
public int hashCode() {
return Objects.hash( credentials, authority );
}
}
@Entity
@Table(name = "credentials")
public class Credentials implements Serializable {
@Id
@Column(name = "credential_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "pk.credentials")
private List<Authorities> authorities;
@NaturalId
@Column(name = "email")
private String email;
@Transient
public Authorities getAuthority()
{
return this.authorities != null && this.authorities.size() > 0
? this.authorities.get(0) : null;
}
// ...
}
推荐阅读
- c# - System.Net.WebException:请求被中止:无法创建 SSL/TLS 安全通道 - dot net framework 4.7.1
- listview - 从下到上滚动时,带有 Streambuilders 的 Flutter ListView 卡住了
- php - 用 foreach 填充多维数组
- php - 使用 javascript 在 php 中删除警报
- statamic - 有没有办法屈服于静态中的可变部分?
- ember.js - 打印出 Ember 模板中的所有父子路由
- javascript - 当我循环测试用例时,为什么 Mocha 会跳过重新分配变量?
- mysql - 如何将多个字符串值合并为一个查询结果
- ruby - 这个奇怪的 SASS 属性语法是什么?
- sql - 无法通过 SQL 和 ACCESS 获取正确的主键