【问题标题】:Spring data jpa - error - with enum type argumentSpring data jpa - 错误 - 带有枚举类型参数
【发布时间】:2021-04-27 14:35:09
【问题描述】:

下面的代码有问题

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginController' defined in file [C:\Users\USERNAME\IdeaProjects...\application\ui\security\controller\LoginController.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginServiceImpl' defined in file [C:\Users\USERNAME\IdeaProjects\...\core\domain\login\LoginServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginRepository' defined in be.mypackage.core.persistence.LoginRepository defined in @EnableJpaRepositories declared on DomainConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List be.mypackage.core.persistence.LoginRepository.findListIdentifiant()!

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginServiceImpl' defined in file [C:\Users\USERNAME\IdeaProjects\....\core\domain\login\LoginServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginRepository' defined in be.mypackage.core.persistence.LoginRepository defined in @EnableJpaRepositories declared on DomainConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List be.mypackage.core.persistence.LoginRepository.findListIdentifiant()!

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginRepository' defined in be.mypackage.core.persistence.LoginRepository defined in @EnableJpaRepositories declared on DomainConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List be.mypackage.core.persistence.LoginRepository.findListIdentifiant()!

Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List be.mypackage.core.persistence.LoginRepository.findListIdentifiant()!


Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode 
 \-[IDENT] IdentNode: 'loginRole' {originalText=loginRole}


Caused by: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode 
 \-[IDENT] IdentNode: 'loginRole' {originalText=loginRole}

我正在尝试从表中检索一些值,但不是全部。我有这个错误。 我不想使用@Transient,因为它会阻止我在其他时间检索密码值。

问题似乎出在枚举字段上,如果我从查询中删除它,使用适当的构造函数,启动程序时查询不再返回错误。

肯定有一些简单的事情我做得不对。

我的请求 jpa

import be.mypackage.core.domain.login.Login;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Query;


import java.util.List;



public interface LoginRepository extends JpaRepository<Login, Integer> {

@Query(value = "SELECT idLogin, identifiant, societe, loginRole FROM Login")

List<Login> findListIdentifiant();

}

我的班级实体登录

package be.mypackage.core.domain.login;

import be.mypackage.core.domain.societe.Societe;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;
import javax.persistence.Transient;

@Entity
@SQLDelete(sql = "UPDATE login SET status_actif = false WHERE id_login=?")
@Where(clause = "status_actif <> 'false'")
public class Login {

    @Id
    @Column(nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer idLogin;

    @Column(length = 100, unique = true)
    private String identifiant;

    //@Transient
    @Column(length = 100)
    private String motDePasse;

    @ManyToOne(fetch = FetchType.LAZY) // OK
    @JoinColumn(name = "no_societe", nullable = false)
    private Societe societe;

    @Transient
    @Column(name = "status_actif", nullable = false)
    private Boolean statusActif;

    @PrePersist
    public void fixStatusActif() {
        this.statusActif = true;
    }

    @Enumerated(EnumType.STRING)
    @Column(name = "role", unique = true, length = 30)
    private LoginRole loginRole;

    public Login() {
    }

    // jpa request work with this constructor
    public Login(Integer idLogin, String identifiant, Societe societe) {
        this.idLogin = idLogin;
        this.identifiant = identifiant;
        this.societe = societe;
    }

    // not work
    public Login(Integer idLogin, String identifiant, Societe societe, LoginRole loginRole) {
        this.idLogin = idLogin;
        this.identifiant = identifiant;
        this.societe = societe;
        this.loginRole = loginRole;
    }

    public Integer getIdLogin() {
        return idLogin;
    }

    public void setIdLogin(Integer idLogin) {
        this.idLogin = idLogin;
    }

    public String getIdentifiant() {
        return identifiant;
    }

    public void setIdentifiant(String identifiant) {
        this.identifiant = identifiant;
    }

    public String getMotDePasse() {
        return motDePasse;
    }

    public void setMotDePasse(String motDePasse) {
        this.motDePasse = motDePasse;
    }

    public Boolean getStatusActif() {
        return statusActif;
    }

    public void setStatusActif(Boolean statusActif) {
        this.statusActif = statusActif;
    }

    public Societe getSociete() {
        return societe;
    }

    public void setSociete(Societe societe) {
        this.societe = societe;
    }

    public LoginRole getLoginRole() {
        return loginRole;
    }

    public void setLoginRole(LoginRole loginRole) {
        this.loginRole = loginRole;
    }

    @Override
    public String toString() {
        return identifiant;
    }
}


类枚举

package be.mypackage.core.domain.login;


public enum LoginRole {

    
    ROLE_ADMIN,
    
    ROLE_MANAGER,
    
    ROLE_EMPLOYEE,
    
    ROLE_EMPLOYEE_READ;


}



我的表登录


findAll 查询适用于枚举,但我无法从查询中排除密码

如您所见,角色(枚举)字段可以很好地使用 findAll,但不符合我的安全要求

【问题讨论】:

  • 尝试使用 nativeQuery = true 就像 here
  • 今晚我会试试这个,但我想我必须手动重做映射。

标签: java spring jpa spring-data-jpa


【解决方案1】:

您不必在查询中列出属性:

@Query(value = "SELECT idLogin, identifiant, societe, loginRole FROM Login")
List<Login> findListIdentifiant();

改为:

@Query(value = "SELECT l FROM Login l")
List<Login> findListIdentifiant();

但是这个查询完全是多余的,因为 JpaRepository 上有一个 findAll() 方法可以做到这一点。

【讨论】:

  • findAll 查询适用于枚举,但我无法从查询中排除密码(参见帖子中的图片)
  • 这是个问题?我的意思是密码不是加密的吗?如果您想在 REST API 中返回它,您可以添加 @JsonIgnore 以将其从序列化中排除
  • 不,密码没有加密,这是管理员要求的一部分... 恢复应用程序密码。 (是的,不是很好)但是你的评论还不错,我会提交给我的经理。
  • 此外,这是一个摇摆应用程序。没有办法用jpa获取枚举吗? (但他说从 2.1 版开始支持此功能)
  • 问题是你不能加载部分实体。但是你可以创建一个带有所有属性的构造函数的常规类。你知道构造函数表达式是如何工作的吗?
猜你喜欢
  • 1970-01-01
  • 2019-07-14
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 2016-09-30
  • 1970-01-01
  • 2017-08-05
相关资源
最近更新 更多