13

I have error in my app, because I use findOne() method. Below my simple code. In User class my id is String email and that's id I'm trying to use in my class UserService like this :

public User findUser(String email){
    return userRepository.findOne(email);
}

but I have this error:

method findOne in interface org.springframework.data.repository.query.QueryByExampleExecutor cannot be applied to given types;
required: org.springframework.data.domain.Example
found: java.lang.String
reason: cannot infer type-variable(s) S (argument mismatch; java.lang.String cannot be converted to org.springframework.data.domain.Example)

User class:

@Entity
@Data
@Table(name = "User")
public class User {
    @Id
    @Email
    @NotEmpty
    @Column(unique = true)
    private String email;

    @NotEmpty
    private String name;

    @NotEmpty
    @Size(min = 5)
    private String password;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Task> tasks;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "USER_ROLE", joinColumns = {
        @JoinColumn(name = "USER_EMAIL", referencedColumnName = "email")
    }, inverseJoinColumns = {@JoinColumn(name = "ROLE_NAME", referencedColumnName = "name")})
    private List<Role> roles;
}

and UserRepository:

public interface UserRepository extends JpaRepository<User, String> {
}
mattt
  • 195
  • 2
  • 5
  • 14
  • The fact that the exception references `org.springframework.data.domain.Example` makes me think you left something from some example code in yours. Look around and double check your configuration. Search for the word `Example` and see what you find – ug_ Mar 11 '18 at 20:01
  • 2
    There is no findOne(ID) method anymore in CrudRepository. Use findById(ID). Read the javadoc. – JB Nizet Mar 11 '18 at 20:13

3 Answers3

22

Use findById or getOne instead of findOne when you want to search only by id.

public User findUser(String email){
    return userRepository.getOne(email); // throws when not found or
                                         // eventually when accessing one of its properties
                                         // depending on the JPA implementation
}

public User findUser(String email){
    Optional<User> optUser = userRepository.findById(email); // returns java8 optional
    if (optUser.isPresent()) {
        return optUser.get();
    } else {
        // handle not found, return null or throw
    }
}

The function findOne() receives a Example<S>, this method is used to find by example, so you need to provide the example object and the fields to check.

You can find how to use the find by example.

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example.matchers

But it is basically something like.

User user = new User();                          
person.setName("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
    .withIgnorePaths("name")                         
    .withIncludeNullValues()                             
    .withStringMatcherEnding();

Example<User> example = Example.of(user, matcher); 
Jose Da Silva Gomes
  • 3,814
  • 3
  • 24
  • 34
  • getOne() does NOT throw when not found. On the contrary, it returns an uninitialized proxy, assuming the entity exists. – JB Nizet Mar 11 '18 at 20:42
  • "Throws: javax.persistence.EntityNotFoundException - if no entity exists for given id." At least that is what it says in the current doc. – Jose Da Silva Gomes Mar 11 '18 at 20:43
  • 1
    It's **allowed** to do that, but it generally won't happen. getOne() simply calls EntityManager.getReference(). https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#getReference-java.lang.Class-java.lang.Object- – JB Nizet Mar 11 '18 at 20:45
  • Good to know it depends on the JPA implementation. So the exception is guaranteed but not necesary thrown in that moment, should at least the thrown when trying to access one property right? – Jose Da Silva Gomes Mar 11 '18 at 20:57
  • Found this, clear now https://stackoverflow.com/questions/32264758/why-does-getone-on-a-spring-data-repository-not-throw-an-entitynotfoundexcept – Jose Da Silva Gomes Mar 11 '18 at 21:18
8

I had something like it. Its because you are using a newer version.

You can fix it by:

return userRepository.findById(email).orElse(null);
Zoe
  • 27,060
  • 21
  • 118
  • 148
Skovgaard
  • 81
  • 1
  • 3
6

The method findOne in JpaRepository are defined as:

<S extends T> Optional<S> findOne(Example<S> example)

Reference

and yo are passing a String as parameter. If you want to find by User.email the method has to be defined as:

User findOneByEmail (String email);

This mecanism is explained in query creation document

lucsbelt
  • 453
  • 2
  • 9