简体   繁体   English

使用 Spring 引导数据 JPA 按需创建表

[英]Creating tables on demand with Spring Boot Data JPA

I'm trying to create a Spring Boot application where I want to create and use database tables on demand, without defining entities / repositories for them.我正在尝试创建一个 Spring 引导应用程序,我想在其中按需创建和使用数据库表,而不为它们定义实体/存储库。

I have got a base Business entity, and BusinessType entity to keep the type of business.我有一个基础业务实体和业务类型实体来保留业务类型。 I want to be able to dynamically create a table for a business type (say Coffeeshop) with its own table (while I can keep the name of the table on the BusinessType table and decide which table to query from there).我希望能够用自己的表为业务类型(比如 Coffeeshop)动态创建一个表(同时我可以将表的名称保留在 BusinessType 表上并决定从那里查询哪个表)。

So without defining an entity and/or creating a CrudRepository for Coffeeshop can I create a table named Coffeeshop and later do some queries on that?因此,在不定义实体和/或为 Coffeeshop 创建 CrudRepository 的情况下,我可以创建一个名为 Coffeeshop 的表,然后对其进行一些查询吗?

If not, what are my alternatives?如果没有,我的替代方案是什么? How do you deal with situations where you have got a base type and allow the system to have more concrete types (persisted and associated with base type) in a typical Spring Data JPA application?在典型的 Spring 数据 JPA 应用程序中,您如何处理具有基本类型并允许系统具有更多具体类型(持久并与基本类型相关联)的情况?

Thank you谢谢

The persistance strategy you describe is not a good fit for JPA.您描述的持久性策略不适合 JPA。 JPA is an ORM (Object relational mapping) strategy where a framework maps data from class based objects to rows in schema defined relational tables. JPA 是一种 ORM(对象关系映射)策略,其中框架将基于 class 的对象的数据映射到模式定义的关系表中的行。 It would complicate the annotation driven implementation to have tables with no corresponding class, or classes without a specific tables.如果表没有对应的 class 或没有特定表的类,这会使注释驱动的实现复杂化。

To solve your problem using JPA, an idomatic solution would be to keep all your businesses in one table (mapped to a Business entity class, as you described), and to have a (foreign) key on the table to allow each row to have a business type.要使用 JPA 解决您的问题,一个惯用的解决方案是将您的所有业务保存在一个表中(映射到业务实体 class,如您所述),并在表上有一个(外)键以允许每一行具有一种业务类型。 Then you could select the set of businesses with a particular type via a query (rather than by targeting a different table.)然后,您可以通过查询(而不是针对不同的表)来 select 具有特定类型的业务集。

Business
id | type       | name           | etc...
1    COFFEESHOP   Alices Coffee

BusinessType
id          | name | industry
COFFEESHOP    Cafe   HOSPITAILITY

Then to get all coffee shops in your system you would define a BusinessRepository method然后要获取系统中的所有咖啡店,您将定义一个 BusinessRepository 方法

@Query(value = "{ 'type': ?0  }")
List<Business> findAllByType(String type);

To solve your problem using the table creation strategy you described, you'd have to write most of the data access layer yourself.要使用您描述的表创建策略解决您的问题,您必须自己编写大部分数据访问层。 You could do this in a handwritten BusinessDAO class (not using JPA or annotations), which would have methods that construct and execute SQL statements using plain JDBC to achieve the required schema manipulations. You could do this in a handwritten BusinessDAO class (not using JPA or annotations), which would have methods that construct and execute SQL statements using plain JDBC to achieve the required schema manipulations. If you wanted a library to emulate the SQL dialect independance that JPA gives you you could check out JOOQ.如果您想要一个库来模拟 JPA 为您提供的 SQL 方言独立性,您可以查看 JOOQ。 This strategy will require a lot more work, and such an application will require schema editing permissions.这种策略需要做更多的工作,而且这样的应用程序需要模式编辑权限。 In enterprise environments that's usually discouraged.在通常不鼓励使用的企业环境中。

A couple of years ago I used to work on such a project - we used to work with spring boot back than but have not used hibernate/jpa/spring data intentionally.几年前,我曾经从事过这样的项目——我们曾经使用 spring 启动,但没有故意使用 hibernate/jpa/spring 数据。

IMHO The whole idea of JPA is to provide entities (as the assumption is that you're a java programmer who doesn't necessarily know anything about SQL / Db Schema) and let hibernate/jpa do its magic and define the schema for you (given the properties). IMHO The whole idea of JPA is to provide entities (as the assumption is that you're a java programmer who doesn't necessarily know anything about SQL / Db Schema) and let hibernate/jpa do its magic and define the schema for you (给定属性)。 Its also possible to go the "other-way-around" and have your tables already and try to create entities so that they will "map" onto the existing structure in the RDBMS.也可以将 go 换成“其他方式”,并让您的表已经存在并尝试创建实体,以便它们“映射”到 RDBMS 中的现有结构上。

What you've describe simply doesn't fit to this approach.你所描述的根本不适合这种方法。 So in our project, since we didn't want to deal with the complexity of queries introduced by hibernate and wanted to optionally go with a dynamic structure like you describe, we've done the following:因此,在我们的项目中,由于我们不想处理 hibernate 引入的查询的复杂性,并希望选择具有您描述的动态结构的 go,因此我们完成了以下操作:

  • Used Flyway to generate the schemas.使用Flyway生成模式。 This tool is integrated with Spring boot so that it gets called when the application starts and checks the schema version, if it has more "recent" scripts - it applies the changes to the DB - something that is called "migrations".该工具与 Spring 引导集成,因此它在应用程序启动时被调用并检查模式版本,如果它有更多的“最近”脚本 - 它将更改应用到数据库 - 这就是所谓的“迁移”。 Another popular alternative is liquidbase , both work with spring boot AFAIK.另一种流行的替代方法是liquidbase ,两者都可以与 spring boot AFAIK 一起使用。
  • We've used JOOQ to avoid writing a plain JDBC queries.我们使用JOOQ来避免编写普通的 JDBC 查询。 If you decide to work with JOOQ (I can totally recommend this tool - it worked great for us, simple, convenient, type-safe), you can read this tutorial to integrate with spring boot.如果您决定使用 JOOQ(我完全可以推荐这个工具 - 它对我们来说非常有用,简单、方便、类型安全),您可以阅读本教程以与 spring 引导集成。 Other alternatives are MyBatis or if you want to go "low-level", use JDBI or maybe Spring's JdbcTemplate.其他替代品是MyBatis ,或者如果你想 go “低级”,使用JDBI或者 Spring 的 JdbcTemplate。 I'm sure there are other alternatives as well.我敢肯定还有其他选择。

So basically with this setup the flow looks like this: In a build time you generate the Java Code (JOOQ) that stands behind the tables.因此,基本上使用此设置,流程如下所示:在构建时,您生成位于表格后面的 Java 代码 (JOOQ)。 This code is no-way near like Hibernate entities, it contains just enough information to prepare the query in JAVA DSL-like language, it doesn't generate queries by itself.此代码与 Hibernate 实体完全不同,它包含的信息足以用 JAVA 类 DSL 语言准备查询,它本身不会生成查询。

When the application starts - it checks the schema and applies migrations (flyway).当应用程序启动时 - 它检查架构并应用迁移(flyway)。 Migrations are source files in which you write the SQL.迁移是您在其中编写 SQL 的源文件。

Now one possible caveat is that you need a permission at the level of RDBMS to actually create tables like that.现在一个可能的警告是,您需要 RDBMS 级别的权限才能实际创建这样的表。 So depending on your organization it might be not be trivial, so I suggest to discuss this approach with your DBA first.因此,根据您的组织,这可能并非易事,因此我建议先与您的 DBA 讨论这种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM