为什么我的jpa存储库返回一个对象,但是此对象上的任何方法调用都给出了一个nullpointer异常?

时间:2022-09-11 16:22:54

I have this code in my account controller.

我的帐户控制器中有此代码。

        Account account = accountRepository.findByUsername(username);

The argument comes from the RESTcontroller argument username that receives the string "henk@gmail.com". The reason why it includes the " " is because I used the javascript command JSON.Stringify(username) before sending it to the controller. When you try to stringify a string it adds an extra pair of "".

该参数来自接收字符串“henk@gmail.com”的RESTcontroller参数用户名。它包含“”的原因是因为我在将它发送到控制器之前使用了javascript命令JSON.Stringify(username)。当您尝试对字符串进行字符串化时,它会添加一对额外的“”。

Now on to my question. How come accountRepository.findByUsername(username) with this argument gives back an account (I checked this by printing:)

现在回答我的问题。如何使用此参数的accountRepository.findByUsername(用户名)返回一个帐户(我通过打印检查了:)

System.out.println("Is account null? " + account == null);

But when I call any method on that account (like toString()) it gives a nullpointer exception? It has something to do with the pair of "" that are encompassing the argument henk@gmail.com, but why is this causing the jpa repository to give back this mysterious account object?

但是,当我调用该帐户的任何方法(如toString())时,它会给出一个nullpointer异常?它与包含参数henk@gmail.com的那对“”有关,但是为什么这会导致jpa存储库回复这个神秘的帐户对象?

The jpa repository is defined like this:

jpa存储库定义如下:

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
    Account findByUsername(String username);
    Account findByUsernameAndPassword(String username, String password);
    Set<Account> findByAdminIsTrue();
}

The account object is defined as this:

帐户对象定义如下:

@Entity
//@JsonIgnoreProperties
//@JsonIdentityInfo(
//        generator = ObjectIdGenerators.PropertyGenerator.class,
//        property = "id",
//        scope = Account.class)
public class Account implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String password;
    private String name;
    private boolean admin;
    private boolean enabled;
    private int remainingStatutoryLeaveHours = 240;
    private int remainingNonStatutoryLeaveHours = 60;

    @JsonIgnore
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "account", cascade = CascadeType.ALL)
    List<LeaveQuery> leaveQueryList;
//

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "account", cascade = CascadeType.ALL)
    List<LaborPeriod> laborperiods = new ArrayList<>();

    @OneToOne
    private Person person;

    @Enumerated
    UserRole userRole = UserRole.USER;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public UserRole getUserRole() {
        return userRole;
    }

    public void setUserRole(UserRole userRole) {
        this.userRole = userRole;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public boolean isAdmin() {
        return admin;
    }

    public void setAdmin(boolean admin) {
        this.admin = admin;
    }

    public List<LaborPeriod> getLaborperiods() {
        return laborperiods;
    }

    public void setLaborperiods(List<LaborPeriod> laborperiods) {
        this.laborperiods = laborperiods;
    }

    public List<LeaveQuery> getLeaveQueryList() {
        return leaveQueryList;
    }

    public void setLeaveQueryList(List<LeaveQuery> leaveQueryList) {
        this.leaveQueryList = leaveQueryList;
    }

    public int getRemainingStatutoryLeaveHours() {
        return remainingStatutoryLeaveHours;
    }

    public void setRemainingStatutoryLeaveHours(int remainingStatutoryLeaveHours) {
        this.remainingStatutoryLeaveHours = remainingStatutoryLeaveHours;
    }

    public int getRemainingNonStatutoryLeaveHours() {
        return remainingNonStatutoryLeaveHours;
    }

    public void setRemainingNonStatutoryLeaveHours(int remainingNonStatutoryLeaveHours) {
        this.remainingNonStatutoryLeaveHours = remainingNonStatutoryLeaveHours;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", admin=" + admin +
                ", enabled=" + enabled +
                ", remainingStatutoryLeaveHours=" + remainingStatutoryLeaveHours +
                ", remainingNonStatutoryLeaveHours=" + remainingNonStatutoryLeaveHours +
                ", leaveQueryList=" + leaveQueryList +
                ", laborperiods=" + laborperiods +
                ", person=" + person +
                ", userRole=" + userRole +
                '}';
    }
}

Anyone an idea?

有人有想法吗?

1 个解决方案

#1


1  

If this statement:

如果这句话:

    account.toString();

is the source of the NPE, then there is only one plausible explanation: the value of account is null.

是NPE的来源,那么只有一个合理的解释:账户的价值为空。


You say that this statement:

你说这句话:

    System.out.println("Is account null? " + account == null);

is telling you that account is not null. Guess what. It isn't!

告诉你该帐户不是空的。你猜怎么着。不是!

The precedence of + is higher than ==. So the statement above is equivalent to:

+的优先级高于==。所以上面的陈述相当于:

    System.out.println(("Is account null? " + account) == null);

which will print false irrespective of the value of account because concatenating a string and null will be a non-null string.

无论account的值如何,都将打印false,因为连接字符串和null将是非空字符串。

Rerun your program with that statement written as:

使用该语句重新运行您的程序:

    System.out.println("Is account null? " + (account == null));

Then you can solve the real problem ... which is figuring out why account is null and how to deal with that.

然后你可以解决真正的问题......这就是弄清楚为什么帐户是空的以及如何处理它。

#1


1  

If this statement:

如果这句话:

    account.toString();

is the source of the NPE, then there is only one plausible explanation: the value of account is null.

是NPE的来源,那么只有一个合理的解释:账户的价值为空。


You say that this statement:

你说这句话:

    System.out.println("Is account null? " + account == null);

is telling you that account is not null. Guess what. It isn't!

告诉你该帐户不是空的。你猜怎么着。不是!

The precedence of + is higher than ==. So the statement above is equivalent to:

+的优先级高于==。所以上面的陈述相当于:

    System.out.println(("Is account null? " + account) == null);

which will print false irrespective of the value of account because concatenating a string and null will be a non-null string.

无论account的值如何,都将打印false,因为连接字符串和null将是非空字符串。

Rerun your program with that statement written as:

使用该语句重新运行您的程序:

    System.out.println("Is account null? " + (account == null));

Then you can solve the real problem ... which is figuring out why account is null and how to deal with that.

然后你可以解决真正的问题......这就是弄清楚为什么帐户是空的以及如何处理它。