从 EntityManager 获取所有映射的实体

Posted

技术标签:

【中文标题】从 EntityManager 获取所有映射的实体【英文标题】:Getting all mapped Entities from EntityManager 【发布时间】:2011-01-01 16:48:00 【问题描述】:

我有一段维护代码应该在特定时间点向特定用户授予选择权限:

grant select on A_DB.A_TABLE to READ_ONLY_USER;

我想对所有表都这样做。我可以在 Oracle 中使用 select * from tab 或在 mysql 中使用 show tables 来获取完整列表,然后继续前进。

但由于我手头已经有了 javax.persistence.EntityManager 对象,我想知道是否有其他方法可以获取所有映射的实体,经理知道(我在后台使用 Hibernate)。

【问题讨论】:

你可以检查这个:: ***.com/questions/43604928/… 【参考方案1】:

截至 2016 年(Hibernate 5.2),getAllClassMetadataConfiguration 均已弃用。

我想这可以代替:

Set<EntityType<?>> entities = sessionFactory.getMetamodel().getEntities();

特别是获取类:

List<?> classes = entities.stream()
                          .map(EntityType::getJavaType)
                          .filter(Objects::nonNull)
                          .collect(Collectors.toList());

【讨论】:

从 HIbernate 3 迁移到 5.2.10。我需要从您定义的“实体”到 PersistentClass。这可能吗? 在这里查看我的答案:***.com/questions/32780664/… 什么是空检查,我们什么时候从 getJavaType 方法中得到空的 javatypes?【参考方案2】:

我可以通过两种方式获取所有映射实体及其对应的 SQL 表(可能还有其他方式)。

如果您可以使用 Hibernate 配置对象,最直接的方法是:

    for(Iterator it = config.getClassMappings(); it.hasNext();)
        PersistentClass pc = (PersistentClass) it.next();
        System.out.println(pc.getEntityName() + "\t" + pc.getTable().getName());
    

或者,您也可以进行更多的转换并从 SessionFactory 中获取相同的信息:

    Map<String, ClassMetadata>  map = (Map<String, ClassMetadata>) sessionFactory.getAllClassMetadata();
    for(String entityName : map.keySet())
        SessionFactoryImpl sfImpl = (SessionFactoryImpl) sessionFactory;
        String tableName = ((AbstractEntityPersister)sfImpl.getEntityPersister(entityName)).getTableName();
        System.out.println(entityName + "\t" + tableName);
    

【讨论】:

我无法进入休眠配置,但第二种解决方案有效。【参考方案3】:

正如 MarcG 的回答所说,getAllClassMetadata() 几年前就被弃用了

截至 Hibernate - 5.4.30.Final - 2021 年 3 月 19 日发布 下面的代码有效,并且不推荐使用

MetamodelImplementor metaModelImpl = (MetamodelImplementor)session.getMetamodel();
Map<String, EntityPersister> entityPersisters = metaModelImpl.entityPersisters();
Collection<EntityPersister> val = entityPersisters.values();               

for (EntityPersister ep : val) 
        AbstractEntityPersister aep = (AbstractEntityPersister)ep;

        System.out.println(aep.getTableName());
        System.out.println(Arrays.toString(aep.getIdentifierColumnNames()));
        for (String propName : aep.getPropertyNames()) 
               System.out.println(propName);
               System.out.println(Arrays.toString(aep.getPropertyColumnNames(propName)));
        
 

【讨论】:

【参考方案4】:

检查此Map 中的可用内容:

((Session) entityManager.getDelegate()).getSessionFactory().getAllClassMetadata() ;

【讨论】:

类元数据实际上仅限于实体本身的属性,不包含任何与映射相关的数据。如果数据库表的名称与实体相同,那就没问题了。 好吧,看起来 getAllClassMetadata 是寻求的解决方案。当然,您的回答更详细。我也许不应该给出提示,而是给出完整的解决方案。不过,我觉得这有问题:)【参考方案5】:

如果你手头有 javax.persistence.EntityManager,下面的方法可以帮你列出所有的表名:

private List<String> getAllTables() 
    List<String> tableNames = new ArrayList<>();
    Session session = entityManager.unwrap(Session.class);
    SessionFactory sessionFactory = session.getSessionFactory();
    Map<String, ClassMetadata>  map = (Map<String, ClassMetadata>) sessionFactory.getAllClassMetadata();
    for(String entityName : map.keySet())
        SessionFactoryImpl sfImpl = (SessionFactoryImpl) sessionFactory;
        String tableName = ((AbstractEntityPersister)sfImpl.getEntityPersister(entityName)).getTableName();
        tableNames.add(tableName);
    
    return tableNames;

【讨论】:

以上是关于从 EntityManager 获取所有映射的实体的主要内容,如果未能解决你的问题,请参考以下文章

06 EntityManager和EntityTransaction

EntityManager方法简介

EntityManager 刷新

持久化实体而不将其附加到 EntityManager

使用计数和连接从休眠的实体中获取行

使用 EntityManager / Hibernate 进行批量更新