如何在多个 Spring Boot 应用程序之间共享 JPA 实体

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

我们希望在公开为微服务的两个应用程序之间共享 Employee。但是Employee有JPA定义,我们如何将其打包为一个可以在多个应用程序之间共享的单独的jar

Spring Boot“AppA”具有以下实体

@Entity
@Table (name = "employees")
public class Employee {

}

Spring Boot“AppB”从“AppA”获取员工

ResponseEntity<Employee[]> response =
  restTemplate.getForEntity(
  "http://localhost:8080/employees/",
  Employee[].class);
Employee[] employees = response.getBody();
spring-boot spring-data-jpa spring-data-rest
3个回答
3
投票

如果您确实需要共享它们并且不想复制和粘贴,您可以通过将共享实体和存储库打包在单独的 Spring 项目(没有 Application.java)上并在下游服务中将该项目声明为 maven/ 来实现这一点gradle 依赖。

假设您已将实体和存储库放入以下包下的单独库中: 在像 my.common.lib.entitiesmy.common.lib.repos

这样的包下

您可以通过在相应的 Spring 应用程序类上使用 @ComponentScan 让 Spring 在您的下游服务 AppA 和 AppB 上发现它们:

应用程序A:

@ComponentScan(basePackages={"my.common.lib.entities", "my.common.lib.repos"})
@SpringBootApplication
ApplicationAppA {


}

3
投票

您必须先将实体包装在

Record
中,然后使用
Corba-SCNR
版本 3 从其他服务访问它。

或者,您可能需要重新考虑您的 微服务架构,因为有两个服务访问并不好 相同的实体/数据库。

好了,拖钓时间结束了。

回答您的问题:您无法以仍然为您提供 JPA/Hibernate 定义的保证的方式在两个服务之间通过 REST 共享实体。 这是为什么?因为 JPA/Hibernate 中的

EntityManager
围绕您拥有的 Java 对象创建了一个包装器,拦截对它的调用,并且会记住您何时更改某些字段,以便它知道当您“刷新”数据库的更改时要生成哪些 sql 语句。这些包装器无法通过 REST 端点进行序列化,至少不能以其他服务可以拾取它们并在第一个服务停止的位置继续的方式进行序列化。

一般来说,直接在 REST 控制器中公开 JPA 实体是一个坏主意。我个人更喜欢创建小型 DTO(数据传输对象),并在其中填充需要公开的数据,并且仅公开 REST 端点中的数据。

因此最好考虑“AppB 需要从 Employee 获取哪些信息”并将这些信息放入 DTO 中,然后将它们公开在 AppA 的 Controller 中。 如果您需要对 AppB 中的 Employee 进行更改,请在 AppA 中创建一个控制器来接受来自 AppB 的请求,然后从 AppB 向 AppA 发送请求。

根据您创建的

EmployeeDTO
的大小,您可以将其放入共享 jar 中或直接复制过来。根据项目的大小,您也可以在 AppA 中的 Swagger/OpenAPI 中描述它并在 AppB 中生成它,但这可能有点矫枉过正。

我希望这会有所帮助。抱歉之前的恶搞。


0
投票

0

我猜你的 spring starter 中的 pom.xml 中有类似的东西

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <excludes>
            <exclude>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </exclude>
        </excludes>
    </configuration>
</plugin>

将其替换为:

<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <configuration>
                            <skip>true</skip>
                        </configuration>
                    </execution>
                    <execution>
                        <phase>package</phase>
                        <configuration>
                            <!--to be imported on other projects-->
                            <classifier>com.l3.plannification_cour</classifier>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

您需要更改分类器值并放入目录的值。然后你只需在启动器的终端上进行 mvn clean install 即可。一切都完成了。在要调用它的 spring 项目中,您添加一个像这样的 scanBasePackages 并将分类器值的名称和目录名称放在 java 目录之后。

@SpringBootApplication(scanBasePackages ={ "com.l3.plannification_cour","com.mvc.gestion_cour"}) 公共类 GestionCourApplication {

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

}

© www.soinside.com 2019 - 2024. All rights reserved.