java.lang.IllegalArgumentException: Failed to create query method in a JpaRepository


java.lang.IllegalArgumentException: Failed to create query method in a JpaRepository



I use the technologies jpa, hibernate, spring boot - data, api REST.



I have the following error:



org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'walletRestService': Unsatisfied dependency expressed through field 'walletRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'walletRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query method public abstract java.lang.Long com.wj.dao.WalletRepository.createWallet(java.lang.Long,java.lang.String)! No property createWallet found for type Wallet!



Here is my code :



Entity user:


package com.wj.entities;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import com.fasterxml.jackson.annotation.JsonManagedReference;

@Entity
public class User implements Serializable{

@Id
@GeneratedValue
private Long id;
private String name;

@OneToMany(mappedBy="user", fetch=FetchType.LAZY)
@JsonManagedReference
private List<Wallet> wallets = new ArrayList<>();

public User() {
super();
}

public User(String name) {
super();
this.name = name;
}



public User(Long id, String name) {
super();
this.id = id;
this.name = name;
}



public User(Long id, String name, List<Wallet> wallets) {
super();
this.id = id;
this.name = name;
this.wallets = wallets;
}

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

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

public List<Wallet> getWallets() {
return wallets;
}

public void setWallets(List<Wallet> wallets) {
this.wallets = wallets;
}


}



Entity wallet:


@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name="user_id")
@JsonBackReference
private User user;

public Wallet() {
super();
}




public Wallet(String name, User user) {
super();
this.name = name;
this.user = user;
}




public Wallet(Long id, String name, User user) {
super();
this.id = id;
this.name = name;
this.user = user;
}



public Long getId() {
return id;
}

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

public String getName() {
return name;
}

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

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}


}



restApi:


@RequestMapping(value="/wallets", method=RequestMethod.POST)
public Wallet save(@RequestBody Wallet wallet) {
User user = wallet.getUser();

Long id = walletRepository.createWallet(user.getId(), wallet.getName());
User boundUser = wallet.getUser();
User simpleUser = new User(boundUser.getId(), boundUser.getName());
wallet = new Wallet(id, wallet.getName(), simpleUser);
return walletRepository.save(wallet);
}

DAO:

package com.wj.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.wj.entities.Wallet;

public interface WalletRepository extends JpaRepository<Wallet, Long>{
Long createWallet(Long id, String name);
}





Show your implementation of WalletRepository.
– mentallurg
Jun 30 at 12:58




2 Answers
2



Trying to do as you told me, he shows me the following error:



org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: com.wj.entities.User.wallets



WalletRepository : DAO


public interface WalletRepository extends JpaRepository<Wallet, Long>{

Long save(Long id, String name);

}



RestService:


@RequestMapping(value="/wallets",
method=RequestMethod.POST)
public Wallet save(@RequestBody Wallet wallet) {
User user = wallet.getUser();

Long id = walletRepository.save(user.getId(), wallet.getName());
User boundUser = wallet.getUser();
User simpleUser = new User(boundUser.getId(), boundUser.getName());
wallet = new Wallet(id, wallet.getName(), simpleUser);
return walletRepository.save(wallet);
}



Entity: user
I modified:


@OneToMany(mappedBy="user", fetch=FetchType.LAZY)
@JsonManagedReference
private List<? extends Wallet> wallets = new ArrayList<>();



This declaration in your WalletRepository interface is not valid for Spring :


WalletRepository


Long createWallet(Long id, String name);



How do you want that Spring guesses what the createWallet() method is designed to create and persist a Wallet entity with a Long id and a String name ?


createWallet()


Wallet


Long id


String name



In fact the methods you declare in your WalletRepository interface are retrieval methods that rely on naming conventions to allow Spring create the queries for you. And create is not referenced in the Spring Data documentation :


WalletRepository


create



4.4.2. Query Creation



The mechanism strips the prefixes find…By, read…By, query…By,
count…By, and get…By from the method and starts parsing the rest of
it.


find…By


read…By


query…By


count…By


get…By



As Spring didn't recognize create, it probably tries to resolve createWallet as a field of the entity. Whereas the message :


create


createWallet



No property createWallet found for type Wallet!



To save an entity, instead use the method provided in the JpaRepository :


JpaRepository


<S extends T> S save(S entity);



which for your repository will be inferred as :


Wallet save(Wallet entity);



And adapt your client code to create the Wallet instance and to pass it to save().


Wallet


save()



Such as :


@RequestMapping(value="/wallets", method=RequestMethod.POST)
public Wallet save(@RequestBody Wallet wallet) {
User boundUser = wallet.getUser();
return walletRepository.save(wallet);
}





I did not really understand your answer. Could you give me an example with my code? thank you
– woodson
Jun 30 at 13:30





Trying to do as you told me, he shows me the following error: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: com.wj.entities.User.wallets
– woodson
Jun 30 at 13:43






You don't need to declare the method. It is already provided in the JpaRepository. But what is the goal of the createWallet() method ?
– davidxxx
Jun 30 at 16:01





It allows me to create a wallet, knowing that a wallet has a user and name. When I call createWallet () in restService it forces me to create it in the DAO. Otherwise what function must I call in restService, to avoid making an error, knowing that to create a wallet I need to set the user.id and the name?
– woodson
Jul 1 at 10:50






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask