使用Hibernate进行Spring启动 - 从另一个项目自动装配存储库

时间:2017-11-19 05:17:07

标签: spring hibernate spring-boot spring-data-jpa autowired

我试图建立两个独立的项目:

  1. myApplicationWorker :后端服务器逻辑
  2. myApplicationCommon :包含将在myApplicationWorker和未来项目之间共享的模型和其他逻辑
  3. myApplicationWorker build.gradle 依赖关系如下所示:

    dependencies {
        compile('org.springframework.boot:spring-boot-starter')
        compile project(':common')
        testCompile('org.springframework.boot:spring-boot-starter-test')
    }
    

    myApplicationCommon build.gradle 依赖关系如下所示:

    dependencies {
        compile('org.springframework.boot:spring-boot-starter-data-jpa')
        compile('mysql:mysql-connector-java')
        compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.9.1'
        compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.9.1'
        compile('org.apache.commons:commons-text:1.1')
        testCompile("com.h2database:h2")
        testCompile('junit:junit:5.0.2')
        testCompile('org.mockito.mockito-core:2.12.0')
    }
    

    (包含测试/模拟/日志记录依赖项以及JPA / MySQL依赖项。)

    简单的hibernate / datasource属性在 application.properties 中定义:

    spring.jpa.hibernate.ddl-auto=none
    spring.datasource.url=url
    spring.datasource.username=username
    spring.datasource.password=password
    

    我有一个" 帐户"模型定义:

    package com.myapplication.common.models;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "accounts")
    public class Account {
        @Id
        private long id;
    
        //Other variables, getters/setters omitted for length
    

    并且帐户模型具有 AccountRepository

    package com.myapplication.common.models.repositories;
    
    import com.myapplication.common.models.Account;
    import org.springframework.data.repository.CrudRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface AccountRepository extends CrudRepository<Account, Long> {
        Account findAccountById(long id);
    }
    

    我的目标是让我的任何项目能够依赖公共项目与后端MySQL数据库进行交互,只需依赖于公共项目即可。我希望这可以在我的工作包中使用:

    package com.myapplication.worker;
    
    import com.myapplication.common.models.repositories.AccountRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.domain.EntityScan;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    
    @SpringBootApplication
    @EnableJpaRepositories(basePackages = {"com.myapplication.common"})
    @EntityScan(basePackages = {"com.myapplication.common"})
    public class Application {
        @Autowired
        private AccountRepository accountRepository;
    
        public static void main(String[] args) {
            Application application = new Application();
            application.testPrintAccountId();
        }
    
        public void testPrintAccountId() {
            System.out.println(accountRepository.findAccountbyId(1).getAccountId());
        }        
    }
    

    当我尝试与testPrintAccountId()中的accountRepository交互时,这给了我一个NPE,但是,当我手动初始化上下文时,它(显然)有效:

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class);
        AccountRepository accountRepository = context.getBean(AccountRepository .class);
        System.out.println(accountRepository .findById(1234).getAccountId());
    
        (Successfully returns result)
    }
    

    我明显误解了Spring和Spring Boot应该如何在这里工作。如何实现我的目标,即能够将我的共同项目中的存储库自动装配到其他项目中?

2 个答案:

答案 0 :(得分:1)

如果要在主类中自动连接依赖项。 Spring还没有将依赖项自动装入App对象。如果要在Spring完成创建和自动装配后调用此方法,请添加带有@PostConstruct注释的方法来执行此操作,例如:

@SpringBootApplication
public class Application {
    @Autowired
    private AccountRepository accountRepository;

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }


    @PostConstruct
    public void testPrintAccountId() {
        System.out.println(accountRepository.findAccountbyId(1).getAccountId());
    }
}

或者您可以在@Component类中使用它,例如@Controller @Service

答案 1 :(得分:0)

万一有人像我一样来这里

这是可能的,因此OP可能还有其他NPE问题。在非核心模块/应用程序中,这对我有用:

@SpringBootApplication
@EnableJpaRepositories("com.package.domain.respositories")
@ComponentScan("com.package.domain")
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }

}

测试运行正常,并且ClientApp从Domain包中加载存储库而没有问题。