Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JPA Hibernate动态实体映射&;运行时的持久性_Hibernate_Jpa_Spring Data_Spring Data Jpa_Hibernate Mapping - Fatal编程技术网

JPA Hibernate动态实体映射&;运行时的持久性

JPA Hibernate动态实体映射&;运行时的持久性,hibernate,jpa,spring-data,spring-data-jpa,hibernate-mapping,Hibernate,Jpa,Spring Data,Spring Data Jpa,Hibernate Mapping,基本上,我们有一个spring引导应用程序,它要求用户可以定义他/她自己的字段集,并且这些字段应该在运行时通过JPA/Hibernate持久化到他们自己的类/表中。这些类将通过bytebuddy动态生成 所有这些都应该动态完成,而无需重新启动应用程序。 Hibernate动态映射不是一个选项,因为我们将完全创建新类并重新映射它们 我也考虑过EAV模型,但这不起作用,因为我们需要为每组数据提供单独的表,所以JSON不能在同一个表中混合 我正在考虑的第一个解决方案是代理EntityManagetFa

基本上,我们有一个spring引导应用程序,它要求用户可以定义他/她自己的字段集,并且这些字段应该在运行时通过JPA/Hibernate持久化到他们自己的类/表中。这些类将通过bytebuddy动态生成

所有这些都应该动态完成,而无需重新启动应用程序。 Hibernate动态映射不是一个选项,因为我们将完全创建新类并重新映射它们

我也考虑过EAV模型,但这不起作用,因为我们需要为每组数据提供单独的表,所以JSON不能在同一个表中混合

我正在考虑的第一个解决方案是代理EntityManagetFactory,当我们有一个新实体要映射时,我将重新创建EntityManagetFactory并向其中添加新的映射实体,我还将hbm2ddl.auto设置为“update”,以确保创建新表方案

问题是,我不知道还有哪些类可能需要代理,我相信我必须代理Hibernate SessionFactory,但我不确定还有多少其他类需要重新创建和代理,我相信这是一条复杂的道路

另一种解决方案是通过使用Hibernate OGM在SQL和NoSQL解决方案之间进行混合,但在这种情况下,我将失去与现有SQL实体之间的任何关系,我不赞成运行第二个NoSQL DB

我还可以探索其他解决方案吗

编辑:

我将使用bytebuddy动态生成新类,它们将具有@Entity注释,生成的类将写入临时jar文件(例如/tmp/myjar.jar)

使用BeanPostProcessor.postProcessAfterInitialization,我将用代理类替换LocalContainerEntityManagerFactoryBean

我还使用LocalContainerEntityManagerFactoryBean.setPersistenceUnitPostProcessors添加了一个额外的处理器来处理新创建的jar中的类


因此,现在在使用bytebuddy创建新类之后,我将手动调用LocalContainerEntityManagerFactoryBeanProxy.afterProperties来完成JPA和hibernate层的所有引导工作,我还将“hibernate.hbm2ddl.auto”属性设置为“update”,以便创建模式(我知道在生产环境中这样做很危险)

Hibernate将实体映射到表,元数据是在引导过程中生成的。因此,在应用程序运行时,您不能动态修改它

但是,只要继续添加新表而不修改现有结构,就可以在体系结构级别解决此问题:

  • 您可以进行所需的类更改
  • 您构建项目工件
  • 将新项目构件部署到新服务器
  • 您可以从负载平衡器将流量从旧服务器实例切换到新服务器实例,而无需停机
  • 或者,只需将NoSQL数据库(如MongoDB)与Hibernate OGM一起使用,因为您的需求无论如何都不适合关系数据库


    但是,如果您已经使用了RDBMS,那么就不要因为这个原因而切换到NoSQL数据库。

    首先,问题是如何在热部署中添加实体类。我们可以通过一些交换工具(spring boot devtools或maven copy resource)来实现。 第二,要构建实体的不同模型,可以使用JPA继承() 或JPA行映射器

    但是,我发现将JSON对象持久化为数据库中的文本更容易,并让服务的使用者(前台或其他服务)来解析它

    另一种方法是尝试在运行时通过类路径加载类。我将尝试将Json对象持久化为文本,并将其类型保存在ddbb中。然后在application.properties中创建其类型和类路径(数据的java类)的映射,然后执行以下操作:

    static{
         Map<String, String> typeClassPathMap = ......// from properties
         File file = new File("c:\\class-path\\");
        // Convert File to a URL
        URL url = file.toURL();          
        // file:/c:/myclasses/
        URL[] urls = new URL[]{url};
        ClassLoader cl = new URLClassLoader(urls);
    }
    
     Class<?> loadClass(String type){
    
        Class clazz = urlClassLoader.loadClass(typeClassPathMap.get(type));
     }
    
    静态{
    映射类型ClassPathMap=…//from属性
    文件=新文件(“c:\\class path\\”;
    //将文件转换为URL
    URL=file.toURL();
    //文件:/c:/myclass/
    URL[]URL=新URL[]{URL};
    ClassLoader cl=新的URLClassLoader(URL);
    }
    类装入类(字符串类型){
    Class clazz=urlClassLoader.loadClass(typeClassPathMap.get(type));
    }
    

    它将在运行时读取类,并可通过属性进行配置。之后,对于每种类型的数据,我们在属性文件中定义su类型和类路径。当数据来自ddbb时,我们使用其类型获取java类,并将其解析为对象。当我们需要创建新类型的数据时,我们将类保留在类路径中,并在属性中进行配置es.

    感谢您的反馈,但基本上我们无法重建应用程序,因为用户希望在运行时创建和填充表格并添加条目。JSON是否在多个DB提供程序上受支持?我们应该支持postgres/h2/mysql,它是否允许is查询特定字段值?2020年,这是否仍然正确在JPA中,实体无法在运行时动态定义?如果您动态定义实体类或XML映射并引导EntityManagerFactory,它将正常工作。您能否找到解决方案,我在运行时创建实体时遇到问题?这是否回答了您的问题?