带有数据 JPA 的 Spring Boot 多模块不工作

问题描述 投票:0回答:3

我有我的多模块 Spring Boot 项目。我将服务、实体和存储库移至核心模块,在战争模块中我只有控制器。

这里有什么问题吗?如果我不使用 JPA,那么我的核心模块工作正常。如果我在核心模块中添加 JPA 依赖项并在我的服务中注入存储库,那么我会收到各种错误,例如存储库的 noclassdefinitionfound、没有服务类型的合格 bean 等。

如何使这个应用程序工作?

父pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <name>appx</name>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.imsx</groupId>
    <artifactId>appx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>core</module>
        <module>webx</module>
        <module>imsx</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>
        <version.jboss.bom>8.2.1.Final</version.jboss.bom>
        <version.wildfly>14.0.1.Final</version.wildfly>
        <version.compiler.plugin>3.8.0</version.compiler.plugin>
        <version.ear.plugin>3.0.1</version.ear.plugin>
        <version.jar.plugin>3.1.1</version.jar.plugin>
        <version.war.plugin>3.2.2</version.war.plugin>

        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>${maven.compiler.source}</source>
                        <target>${maven.compiler.target}</target>
                    </configuration>
                    <version>${version.compiler.plugin}</version>
                </plugin>
                <plugin>
                    <groupId>org.wildfly.plugins</groupId>
                    <artifactId>wildfly-maven-plugin</artifactId>
                    <version>${version.wildfly.maven.plugin}</version>
                    <inherited>true</inherited>
                    <configuration>
                        <skip>true</skip>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

下面是我的 Ear 模块 pom。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>appx</artifactId>
        <groupId>org.imsx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>imsx</artifactId>
    <packaging>ear</packaging>

    <name>appx: EAR Module</name>

    <dependencies>
        <dependency>
            <groupId>org.imsx</groupId>
            <artifactId>webx</artifactId>
            <version>${project.version}</version>
            <type>war</type>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ear-plugin</artifactId>
                <version>${version.ear.plugin}</version>
                <configuration>
                    <version>7</version>
                    <defaultLibBundleDir>lib</defaultLibBundleDir>
                    <modules>
                        <webModule>
                            <groupId>org.imsx</groupId>
                            <artifactId>webx</artifactId>
                            <contextRoot>/imsx</contextRoot>
                            <bundleFileName>webx.war</bundleFileName>
                        </webModule>
                    </modules>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <configuration>
                    <filename>${project.artifactId}.ear</filename>
                    <skip>false</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

这是我的核心模块 pom,带有 JPA 和 mysql 依赖项。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>appx</artifactId>
        <groupId>org.imsx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>core</artifactId>
    <packaging>jar</packaging>
    <name>appx: Core Module</name>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <scope>provided</scope> <!-- I tried by removing this provided scope as well and got different error in repository level like datasource is not found -->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>${version.jar.plugin}</version><!--$NO-MVN-MAN-VER$ -->
            </plugin>
        </plugins>
    </build>

</project>

最后我有了我的 war 模块 pom.xml。我已经在其中包含了核心模块。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>appx</artifactId>
        <groupId>org.imsx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>webx</artifactId>
    <packaging>war</packaging>

    <name>appx: WAR Module</name>

    <url>http://wildfly.org</url>
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <distribution>repo</distribution>
            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
        </license>
    </licenses>

    <dependencies>

        <dependency>
            <groupId>org.imsx</groupId>
            <artifactId>core</artifactId>
            <version>${project.version}</version>
            <type>jar</type>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

我在核心模块中有 application.properties,我在其中指定了我的数据库连接。

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/bootear?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update

我的 war 模块的属性文件中没有任何内容。

这是我的Java代码:

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value="/test", method=RequestMethod.GET)
    public String test() {
        Optional<User> user = userService.findUserById(1);
        System.out.println(user.isPresent());
        return "Search Completed...";
    }
}


public interface UserService {
    Optional<User> findUserById(Integer id);
}


@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public Optional<User> findUserById(Integer id) {
        return userRepository.findById(id);
    }
}

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

}

如果我将所有这些代码都放在一个 war 模块中,那么它就可以正常工作。这是什么问题?

我正在 Wildfly 服务器中部署此 EAR。它仍然不起作用,破坏了我 2 天的时间。

spring-boot spring-data-jpa multi-module
3个回答
9
投票

发生这种情况是因为 Spring Boot 默认情况下仅在类的同一包/子包中使用 @EnableAutoConfiguration (或 @SpringBootApplication)注释查找存储库。

如果您想手动指示存储库的位置,请使用 @EnableJpaRepositories 注释并添加适当的 basePackages 值,如下所示:

@SpringBootApplication(scanBasePackages = "com.xyz")
@EnableJpaRepositories(basePackages = "com.xyz")
public class Application {

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

这样,Spring Boot 就会找到您的存储库,即使它们位于另一个模块中,您只需要遵守包的命名约定即可。

有关此内容的更多信息在 spring 文档中(第 83.3 点):
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html


1
投票

最简单的处理方法是将模块代码放在与主应用程序所在的包命名相同的包中。Spring 将自动发现 JPA 实体。

这可以在下图中看到,我有两个模块,服务器有 JPA,应用程序只有来自 spring 初始化程序的

@SpringBootApplication

如果您想有不同的命名,那么您应该使用

@EnableJpaRepositories(basePackages = {"you.package.name1","you.package.name2"})
@SpringBootApplication


0
投票

对于仍在为此苦苦挣扎的人,这个解决方案在 Spring Boot 2.7.3 上对我有用。我假设您的模块的包是

your.package.package1
your.package.package2

就我而言,两个包中都有实体和存储库,因此我需要扫描两者,从而获得更通用的

basePackages
值。

package your.package.package1;

@SpringBootApplication
@EntityScan(basePackages = "your.package")
@EnableJpaRepositories(basePackages = "your.package")
public class Application {
    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.