【发布时间】:2018-08-06 08:58:40
【问题描述】:
我非常熟悉“旧版”Spring 4 应用程序。 “遗留”是指不使用 Spring Boot 并使用 application-context.xml 文件和注释。但是,我是 Spring Boot 和 Configuration 类的新手。
我正在创建一个新的 Spring Boot 应用程序,并将一些代码移动到我的旧 Spring 应用程序到这个新的 Spring Boot 应用程序。有了这个,我正在实现 Spring Data JPA?
我已经有了实体,所以我只是把它带进来。我有一个正确的 application.properties 设置。我按照我看到的所有示例中的描述创建了存储库,因此我有一个如下所示的存储库:
@Repository("contactDao")
public interface ContactDao extends CrudRepository<ContactEntity, Long>
{
}
所以,据我了解,findOne(Long id) 和 findAll() 等有很多函数。所有这些方法都是内置的。我什至能够对读取、写入到数据库,一切都很好。
所以,我现在想知道......我需要创建实现吗?我的意思是,因为我没有 EntityManager ...我需要一个吗?
我现在看到的所有示例,都显示了与上面类似的界面,但没有@Repository 注释:
public interface ContactDao extends CrudRepository<ContactEntity, Long>
{
}
我现在看到需要实现的示例:
@Repository("contactDao")
public class ContactDaoImpl implements ContactDao
{
@PersistenceContext
private EntityManager entityManager;
@Override
public ContactEntity findOne(Long contactId)
{
return entityManager.findOne(contactId);
}
}
我认为 Spring Data JPA 的承诺是不必有 Impl,但接口就足够了????????????
出现这种情况的原因是因为我现在正在测试我的业务服务,它抱怨我缺少 EntityManagerFactory ...我认为我不需要一个。
在澄清方面的任何帮助将不胜感激。我正在查看 Google 并访问所有类型的站点和 github 项目,但其中一些站点和项目....如果它们不是从 2017 年开始的,它们很可能已经过时了。
我只想要按照当前标准构建这个项目的正确方法。
更新:
1) 放回我的接口 2) 删除了实现代码 3) DAO/Repository 代码测试正常 4) 新增业务服务:
public interface ContactService
{
List<ContactEntity> getAllContacts();
List<ContactEntity> getContactsByUserId(long userId);
ContactEntity getContactById(long contactId);
ContactEntity add(ContactEntity newContact);
ContactEntity update(ContactEntity newContact);
void remove(long contactId);
}
这是服务的实际实现:
@Transactional
@Service("contactService")
public class ContactServiceImpl implements ContactService
{
@Autowired
private ContactDao contactDao; // THIS ERRORS
@Override
public List<ContactEntity> getAllContacts()
{
List<ContactEntity> contactList = (List<ContactEntity>) contactDao.findAll();
return contactList;
}
@Override
public List<ContactEntity> getContactsByUserId(long userId)
{
UserEntity userEntity = new UserEntity();
userEntity.setUserId(userId);
List<ContactEntity> contactList = contactDao.findByUser(userEntity);
return contactList;
}
... other methods ...
}
这是测试设置:
@Configuration
@ComponentScan("com.tomholmes.springboot.phonebook.server")
@EnableJpaRepositories(basePackages=
{"com.tomholmes.springboot.phonebook.server"})
@PropertySource(value = "classpath:application.properties")
public class TestServiceContextConfiguration
{ }
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestServiceContextConfiguration.class)
@Transactional
public class BaseServiceImplTests
{ }
最后,这是测试本身:
public class ContactServiceImplTest extends BaseServiceImplTests
{
@Autowired
private ContactService service;
@Test
public void testFetchAll() throws Exception
{
List<ContactEntity> contactEntityList = service.getAllContacts();
assertNotNull(contactEntityList);
}
}
这是错误:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'contactEmailService': Unsatisfied dependency expressed through field 'contactEmailDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contactEmailDao': Cannot create inner bean '(inner bean)#70ab80e3' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#70ab80e3': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contactEmailDao': Cannot create inner bean '(inner bean)#70ab80e3' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#70ab80e3': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:313)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1531)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 44 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#70ab80e3': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:448)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299)
... 57 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 65 more
【问题讨论】:
-
阅读参考文档。不是随机的例子(我们一无所知)。您的最后一个示例甚至无法编译,因此您找到它的来源不可靠。如果您有异常,并且想知道原因,请发布错误堆栈跟踪以及相关代码/配置。不要随意尝试或随意猜测。
-
你不需要 Spring Data 接口上的 `@Repository´ 注释。如果您看到使用该注释的实现类,则它不是 Spring Data。参见例如本指南:spring.io/guides/gs/accessing-data-jpa
-
@JBNizet 我已阅读参考文档,但不是很清楚,如果是,就不会有这些问题。是的,我有一个例外,即自动装配 ContactDao 时我的服务代码没有找到 entityManagerFactoryBean ......那么它在哪里?它不在 Repository 中,是否需要在 Service 中?
-
添加@Reposity 似乎并没有伤害任何东西,但它并没有解决我在哪里、为什么、如何需要 EntityManagerFactory 的问题。就像我说的,我是从一个遗留应用程序移植过来的,并试图通过使用“遗留”Spring 应用程序来学习 Spring Boot。
标签: java spring spring-boot spring-data-jpa