Can I choose the name of my jpa repository? - spring

I have to name my interface that extends the CrudRepository
with a spacific name (I use spring and Jpa)
i.e.
public interface UserRepository extends CrudRepository<User, Long> {}
so in this case I have a Entity with name UserRepository
I tried annotation
#Entity(name="UserCustomRepository")
public interface UserRepository extends CrudRepository<User, Long> {}
but it doesn't work...

Apparently it's not possible according to the documentation, see 1.3.3.1. XML Configuration:
Each of these beans will be registered under a bean name that is derived from the interface name, so an interface of UserRepository would be registered under userRepository.
Why do you need a custom name? Besides your example with #Entity(name="UserCustomRepository") is completely broken, #Entity is used to mark JPA entities, not Spring beans/repositories.

Related

Why spring data jpa unnecessary #Repository?

I've looked through various documents and questions about it, but I haven't been able to find a clear answer.
I don't know how an interface that extends JpaRepository can be registered as a bean, and why it doesn't need the #Repository annotation.
In Spring, an interface cannot register a bean with that type without an implementation.
So I tried experimenting like JpaRepository myself, but it didn't work.
// JpaRepository
#NoRepositoryBean
public interface WackRepository {
}
// SimpleJpaRepository
#Repository
public class WackRepositoryImpl implements WackRepository {
}
public interface HelloRepository extends WackRepository {
}
#RestController
#RequiredArgsConstructor
public class HelloController {
private final HelloRepository helloRepository;
}
Parameter 0 of constructor in com.example.demo.HelloController required a bean of type 'com.example.demo.HelloRepository' that could not be found
HelloController, of course, has no implementation, so it is not registered as a bean and throws an exception.
Spring Data detects extensions of the Repository Interface.
In Spring Boot the interfaces extending Repository are found automatically without Spring Boot or if the interfaces are not below the SpringBootApplication in the package hierarchy you have to configure the packages:
#EnableJpaRepositories("com.acme.repositories")
Source: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.create-instances

Spring JPA: Parameter 0 of constructor in ... required a bean of type ... that could not be found

I do a simple web app but on start I get that error. I'm using Spring JPA. The message's about Spring could not find any bean to do autowired. But if I use CrudRepository I always have standard repository implementation. I can't get why Spring can't find own bean? What do I do wrong?
Service layer
#Controller
#RequestMapping("/api/v1/get")
public class UserService {
private final UserRepository repository;
#Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
Add annotation #Repository - it will allow Spring to discover this repository during Component Scan
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
I get it: I forgot to add default constructor for my model class. And if I use this class in Spring jpa CrudRepository<User, Long> it has to be with some default constructor.

Using #Query witouht extends from JpaRepository

I am trying to execute system request using #Query. So, I do not have to extends JpaRepository and create an entity for no purpose.
I get this error:
Field myDAO in myPackage.impl.MyService required a bean of type 'myPackage.dao.MyDAO' that could not be found.
At MyService, I autowired MyDAO.
public class MyService implements IMyService {
#Autowired
private MyDAO myDAO;
#Override
public List<String> getAllTablesName() {
return myDAO.getAllTablesName();
}
}
I try to add #Repository but nothing is changed
#Repository
public interface MyService{
#Query(value ="SHOW TABLES FROM :tableName",nativeQuery = true)
public List<String> getAllTablesName(#Param("tableName") String tableName);
}
How can I solve this problem ?
While you do not have to extend JpaRepository you'll at least have to extend Repository
If you really don't have an entity you probably shouldn't use JPA in the first place which is all about mapping entities to database tables.
If you just want to execute statements a better fit might be a simple class with an injected JdbcTemplate or NamedParameterJdbcTemplate.

Custom repository

I have in my project a few entity that have the same property (for sample 'name') so, it's possible to create a repository with a custom select to use in that's entities? so instead I extend my repository from JpaRepository I extend MyCustomJpaRepository and the MyCustomJpaRepository extends the JpaRepository to grant the basic functions from JpaRepository too?
tks
Yes you can define a common interface repository which extends JpaRepository by marking it with the annotation #NoRepositoryBean:
#NoRepositoryBean
public interface BaseRepository<T extends BaseEntity, ID extends Serializable> extends JpaRepository<T, ID> {
//common methods
}
However, you still must have a dedicated interface for each of your concrete entities which extend this custom interface.

Understanding repositories in Spring Data

I want to create a "generic" repository that query data from multiple entities. If I do that:
#Repository
public interface MyRepository {
#Query("select r from Role r")
List<Role> getRoles();
}
I get an error because Spring doesn't find an implementation to inject when a MyRepository instance is required. So far, so good. Now, If I do this:
#Repository
public interface MyRepository extends JpaRepository {
#Query("select r from Role r")
List<Role> getRoles();
}
I get an error because Object is not a JPA managed type (JpaRepository is generic). Ok, again. If I do this:
#Repository
public interface MyRepository extends JpaRepository<User, String> {
#Query("select r from Role r")
List<Role> getRoles();
}
It works. Why? I'm declaring a JpaRepository for entity User, not Role. Why does JpaRepository need a concrete entity even when the queries will be against another one?
Every repository in Spring Data has to extend the Repository interface, that is a generic interface, so you always have to specify the entity you are gonna work with and you can't do anything about it because it is how Spring Data is implemented. You can find more information here about creating repositories:
http://docs.spring.io/spring-data/jpa/docs/1.4.0.M1/reference/html/repositories.html
On the other hand, of course you can specify one entity to the repository and then add methods that return other type of entities because in your interface you can add whatever you want (also notice that Repository interface has no methods). But if you want to use the methods of the parent interface you have to use the entity you specified.
In your example, you could do what #M. Deinum suggested and create a JpaRepository<Role, Long> and use the findAll query, that makes much more sense. Using a JpaRepository<User, String> as you are doing is just a misuse of the framework.

Resources