使用Spring Boot Data读取MySQL数据

时间:2016-12-28 22:31:20

标签: mysql spring groovy

我正在尝试使用Spring Data创建一个从MySQL读取数据的框架。最终目标是能够编写自动化测试,可以从两个不同的MySQL dbs读取数据并比较数据(例如,确保数据正确复制)。我目前在实际使Spring代码工作时遇到了很多麻烦(我之前从未使用过Spring,我已经尝试修改我在网上找到的各种教程代码,但到目前为止还没有得到它工作。)

这就是我所拥有的。

的MySQL 表:凭证 columns:id(int),password_hash(string) 其中有4个条目。

项目布局:

src/main
  groovy
    domain
      Credentials
    repository
      CredentialsRepository
  resources
    application.properties
src/test/groovy/
  CredentialsTest

的build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'gs-accessing-data-jpa'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.7'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.3.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.4.3.RELEASE'
    testCompile 'junit:junit:4.11'
}

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/my_db
spring.datasource.username=my_user
spring.datasource.password=my_password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true

Credentials.groovy

package domain

import org.springframework.data.annotation.Id

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Table

@Entity
@Table(name = 'credentials')
class Credentials {
    @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name='id')
    int id

    @Column(name='password_hash')
    String passwordHash

    protected Credentials() {}

    @Override
    String toString() {
        "Credential: [id=${id}, passwordHash=${passwordHash}]"
    }
}

CredentialsRepository.groovy

package repository

import domain.Credentials
import org.springframework.data.repository.CrudRepository

interface CredentialsRepository extends CrudRepository<Credentials, Integer> {
}

CredentialsTest.groovy

import domain.Credentials
import repository.CredentialsRepository
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner

import static org.junit.Assert.assertEquals

@RunWith(SpringJUnit4ClassRunner.class) //@EnableJpaRepositories(['domain.Credentials'])
@SpringBootTest(classes = MysqlJpaDemoApplication.class)
class CredentialsTest {
    @Autowired
    CredentialsRepository credentialsRepository

    @Test
    void testLoadCredentials() {
        List<Credentials> credentialsList = credentialsRepository.findAll() as ArrayList<Credentials>
        assertEquals(20, credentialsList.size())
    }
}

运行testLoadCredentials测试会给出以下stacktrace:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'CredentialsTest': Unsatisfied dependency expressed through field 'credentialsRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'repository.CredentialsRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    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:1225)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:386)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    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.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'repository.CredentialsRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1474)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 33 more

2016-12-28 14:14:32.638  INFO 39748 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@742ff096: startup date [Wed Dec 28 14:14:32 PST 2016]; root of context hierarchy

Process finished with exit code 255

2 个答案:

答案 0 :(得分:1)

似乎您用于配置测试的应用程序类MysqlJpaDemoApplication位于默认(顶级)包中。由于Spring在使用@ComponentScan时会运行一些检查,因此会阻止您的应用程序扫描整个类路径。

您应该将MysqlJpaDemoApplication移至新的包裹,即com.example。您的源文件夹如下所示:

src/main
  /groovy/com/example
  |-- /domain
  |   |-- Credentials.groovy
  |-- /repository
  |   |-- CredentialsRepository.groovy
  |-- MysqlJpaDemoApplicatin.groovy  

答案 1 :(得分:1)

看起来这就是它的工作原理:

com.example/
  domain/
    Credentials
  repository/
    CredentialsRepository
  SpringConfig

Credentials.groovy

@Entity
@Table(name = 'credentials')
class Credentials {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    int id

    @Column(name='password_hash')
    String passwordHash

    protected Credentials() {}

    @Override
    String toString() {
        "Credential: [id=${id}, passwordHash=${passwordHash}]"
    }
}

CredentialsRepository

interface CredentialsRepository extends CrudRepository<Credentials, Integer> {}

SpringConfig.groovy

@Configuration
@EnableAutoConfiguration
@ComponentScan('com.example')
class SpringConfig {}

CredentialsTest.groovy

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=SpringConfig.class)
@SpringBootTest(classes = SpringConfig.class)
class CredentialsTest {

    @Autowired
    CredentialsRepository credentialsRepository

    @Test
    void testLoadCredentials() {
        List<Credentials> credentialsList = credentialsRepository.findAll() as ArrayList<Credentials>
        assertEquals(4, credentialsList.size())
    }
}