I am working with SpringMVC+Hibernate, I want to apply Inheritance in DAO layer, I am doing like below:
BaseDao.java
public interface BaseDao
{
public Serializable save(Object object) throws DataAccessException,
HibernateException;
public void merge(Object object) throws DataAccessException,
HibernateException;
public void flush() throws DataAccessException,HibernateException;
}
EmpDao.java
public interface EmpDao extends BaseDao{
}
BaseDaoImpl.java
#Repository
public class BaseDaoImpl implements BaseDao{
// Implementation for baseDao methods
}
EmpDaoImpl .java
#Repository
public class EmpDaoImpl extends BaseDaoImpl implements EmpDao{
// Implementation
}
But I am getting below error:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type
[BaseDao] is defined: expected single matching bean but found 2
What am I missing here?
If you really want to have both BaseDaoImpl and EmpDaoImpl as two beans in your Spring container, you need to tell Spring which one to use wherever you have an #Autowired field of type BaseDao using #Qualifier annotation.
Related: Understanding Spring #Autowired usage
It seems like you're trying to inject BaseDao and Spring is complaining there are two candidates.
I think this is actually a design problem. You wanted to use BaseDaoImpl both as a concrete bean that you use directly and also as a base class for other DAOs. This is bad because the sub-classes does not actually extend but simply uses their parent class. The better pattern would be to get rid of the extends and simply inject the BaseDaoImpl into the other DAOs.
Also, the interfaces looks superfluous. If you're working around the proxy problem, just use proxyTargetClass.
You can use generic types like this
BaseDao.java
public interface BaseDao<EntityType extends Object>
{
public Serializable save(EntityType entity) throws DataAccessException,
HibernateException;
public void merge(EntityType entity) throws DataAccessException,
HibernateException;
public void flush() throws DataAccessException,HibernateException;
}
BaseDaoImpl.java
#Repository
public abstract class BaseDaoImpl<EntityType extends Object> implements BaseDao<EntityType>{
// Implementation for baseDao methods
}
EmpDao.java
public interface EmpDao extends BaseDao<Employee>{
}
EmpDaoImpl .java
#Repository
public class EmpDaoImpl extends BaseDaoImpl<Employee> implements EmpDao{
// Implementation
}
You need to add the #NoRepositoryBean on the BaseDao interface so spring would not create a bean for it, as well as for EmpDao I assume
Related
I have generic base repository defined as follows:
#NoRepositoryBean
public interface IBaseRepository<Template extends BaseModel, Id > extends
ElasticsearchRepository<Template,Id>, ICustomRepository{
}
My ICustomRepository repository interface is defined as follows:
#Repository
public interface ICustomRepository {
void someCustomFunction();
}
public class CustomRepositoryImpl implements ICustomRepository{
#Override
void someCustomFunction(){
}
}
Now when I use the baserepository as:
#Repository
public interface OrderRepository extends BaseRepository<OrderModel,Long>{
}
when I Autowired OrdeRepository in my service class it gives me compile error:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'OrderRepository ' defined in
abc.example.OrderRepository defined in
#EnableElasticsearchRepositories declared on ElkApplication:
Invocation of init method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException: No
property someCustomFunction found for type OrderModel!
Can someone please suggest whats going wrong here and how to resolve this?
Converting comment to answer
ICustomRepo
#Repository
public interface ICustomRepository {
void someCustomFunction();
}
IBaseRepository
#NoRepositoryBean
public interface IBaseRepository<Template extends BaseModel, Id > extends
ElasticsearchRepository<Template,Id>, ICustomRepository{
}
OrderRepository
#Repository
public interface OrderRepository extends IBaseRepository<OrderModel,Long>{
}
OrderRepository is a repository interface and a bean is created by a spring bean processor but this OrderRepository does not implement someCustomFunction and even spring has no idea about its implementation except it knows it has been implemented by CustomRepositoryImpl so at bootstrap/startup spring throws an error.
So instead of just having the definition of someCustomFunction we need to implement this in ICustomRepository, thanks to Java 8 we can implement the method in the interface as well
#Repository
public interface ICustomRepository {
default void someCustomFunction() {
// some code here
}
}
This code will be working fine, JDK and other proxies will work on this method as well, also we can apply AOP on someCustomFunction.
It is also possible to override this method in any repository given that's also using the default and #Override.
#Repository
public interface OrderRepository extends IBaseRepository<OrderModel,Long>{
#Override
default void someCustomFunction() {
// some code here
}
}
Following are my code
#RestController
public class EmployeeController {
#Autowired
EmployeeService empService;
public EmployeeController (EmployeeService Impl empServiceImpl) {
super();
this.empService = empServiceImpl;
}
}
#Service
public interface EmployeeService {
public List<EmployeeDTO> getAllEmployeeDetails()
}
public class EmployeeServiceImpl {
public List<EmployeeDTO> getAllEmployeeDetails(){
//methods business logic and repo call goes here
}
}
When I start my server I am getting below error.
Parameter 1 of constructor in
com.app.in.controller.EmployeeController required a bean of type
'com.app.in.service.EmployeeServiceImpl' that could not be found
My understanding might be wrong. If I annotate the EmployeeSeriveImpl class also with #Service then it working.Is that is the correct way to do it ? My question is the service interface is annotated with #Service still why its implementation is also required to annotation. Please let me know if I miss something in that ? What is the standard method to solve this issue ?
You can get your dependency injected using a constructor. And #Autowired is optional in this case.
This is your example, but with a few corrections:
#RestController
public class EmployeeController {
// private final is a good practice. no need in #Autowire
private final EmployeeService empService;
// this constructor will be used to inject your dependency
// #Autowired is optional in this case, but you can put it here
public EmployeeController (EmployeeService empServiceImpl) {
this.empService = empServiceImpl;
}
}
I assume you have an interface EmployeeService and class EmployeeServiceImpl which implements that interface and is Spring Bean.
Something like this:
#Service
public class EmployeeServiceImpl implements EmployeeService {}
Why this #Service is needed? When you put this annotation on your class, Spring knows this is a bean that Spring should manage for you (container will create an instance of it and inject it wherever it is needed).
Check Spring docs to get more details about Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null.
I'm working on a project that uses SpringBoot 2.0.5 version, Spring Data JPA to persists and retrieve records using JPA. I autowired SimpleJpaRepository in the service layer. But while starting my application, it failed with
"NoSuchBeanDefinitionException"- No qualifying bean of type
'org.springframework.data.jpa.repository.support.SimpleJpaRepository<?, ?>'
available: expected at least 1 bean which qualifies as autowire candidate.
My controller, service and DAO are like below
Controller class:
#Controller
public class MyController{
#Autowired
private MyService<Person,PersonPK> service;
Service layer as
public interface MyService<V,K>{
methods defined
}
#Service("service")
public class MyServiceImpl<V,K> implements MyService<V,K>{
#Autowired
private SimpleJpaRepository<V,K> repository; // This dependency is failing
}
Application as :
#SpringBootApplication (exclude = {SecurityAutoConfiguration.class})
#EnableJpaRepositories
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Is my approach incorrect? Is that not the correct way of autowiring the SimpleJpaRepository.
There is no need for me to extend SimpleJpaRepository as Spring provided JPARepository is good for me, for now.
Thanks
You still need to create a repository interface that extends JpaRepisitory, or the spring repository type of your choice.
To quote the spring data documentation:
1.2.1 Defining repository interfaces
As a first step you define a domain class-specific repository interface. The interface must extend
Repository and be typed to the domain class and an ID type. If you
want to expose CRUD methods for that domain type, extend
CrudRepository instead of Repository.
Once you do create a new repository type, you will autowire by that type rather than the SimpleJpaRepository.
One way to get an implementation of the SimpleJpaRepository is by using a Configuration class to create an instance as a bean that you will use inside your service.
#Configuration
public class PersistanceConfiguration {
#PersistenceContext
private EntityManager entityManager;
#Bean
public SimpleJpaRepository<YourEntity, Long> getYourEntitySimpleRepository() {
return new SimpleJpaRepository<>(YourEntity.class, entityManager);
}
}
And inject it to your service as you would do with a JpaRepository, for example:
#Service
public class YourEntityServiceImpl<YourEntity, Long> implements YourEntityService {
private JpaRepository<YourEntity, K> repository;
private SimpleJpaRepository<YourEntity, K> simpleRepository;
#Autowired
public YourEntityServiceImpl(YourEntityRepository repository, SimpleJpaRepository<YourEntity, Long> simpleRepository) {
this.repository = repository;
this.simpleRepository = simpleRepository;
}
}
You should create a repository interface that extending JpaRepisitory.
#Repository
public interface MyRepository extends JpaRepisitory<T, ID> {
//
}
And the you should Autowired in your service class.
#Service("service")
public class MyServiceImpl<V,K> implements MyService<V,K>{
#Autowired
private MyRepository myRepository;
}
I've googled so many times for how to access entity manager in spring boot, and did what posts said, but it didn't work. I want to access Entity Manager so that i can do some custom query operation. Here i defined the custom interface in a dependent package named 'customrepository':
public interface PostRepositoryCustom {
void refresh(Post post);
}
Then I implemented this interface in another package named 'customrepositoryimpl':
public class CustomPostRepositoryImpl implements PostRepositoryCustom {
#PersistenceContext
private EntityManager em;
#Override
public void refresh(Post post) {
em.refresh(post);
}
}
Finally, I defined a standard repository interface which extends 'CrudRepository' and the custom repository:
public interface PostRepository extends CrudRepository<Post,Long>,PostRepositoryCustom {}
Every steps i followed What i googled and Official Documents, BUT when i run my application, i get this:
Error creating bean with name 'postRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract void com.example.demo.customrepository.PostRepositoryCustom.refresh(com.example.demo.model.Post)! No property refresh found for type Post!
Why? Anyone tell me where should i correct my mistakes?
Spring cannot locate the beans, so try annotate with #Repository
#Repository
public class CustomPostRepositoryImpl implements PostRepositoryCustom {
#PersistenceContext
private EntityManager em;
#Override
public void refresh(Post post) {
em.refresh(post);
}
}
and
#Repository
public interface PostRepository extends CrudRepository<Post,Long>{
}
I have the following problem.
I have a generic class A
public class A<T, DAO extends JpaRepository<?, ?>>
{
#Autowired
protected DAO daoObject;
......
and there I am trying inject a genreic DAO-object of the JpaRepository-type.
If I have only one implemetation of injected object(of JpaRepository), then there is no problem, but if I have more then one, then spring doesn't know which object it is to inject and throws an exception.
The question is: How can I dynamish based on generic information, inject the correct object?
Thank you.
public interface IRegisteredUserDAO extends JpaRepository<RegisteredUser, String> {
}
public interface IMailLogDao extends JpaRepository<MailLog, Long> {
findByTo(String to);
}
and i used it so
public class RegisteredUserVM extends YBTableViewModel<RegisteredUser, IRegisteredUserDAO>
{
UPDATE:
public class MailLogVM extends YBTableViewModel<MailLog, IMailLogDao>
{
}
You should be able to do this using the latest Spring 4 RC1. Versions before that do not support generic injection at all. See this ticket and related commits for details.
You can use Spring's #Qualifier annotation to inject the correct bean:
#Autowired
#Qualifier("IRegisteredUserDAOImpl")
protected DAO daoObject;
Here the bean with qualifier value "IRegisteredUserDAOImpl" is wired.