Hibernate升级到5.2 – 创建会话工厂并替换PersistentClass以获取实体类属性

我目前正在将我的Hibernate版本升级到最新版本5.2.10。 我在HibernateUtil中替换了我创建SessionFactory的代码。

4.3.11.Final(上一篇)

public class HibernateUtil { private HibernateUtil() {} private static SessionFactory sessionFactory; private static Configuration configuration; public static Configuration getConfiguration() { return configuration; } private static SessionFactory buildSessionFactory() { try { if(sessionFactory == null) { configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()).build(); sessionFactory = configuration .buildSessionFactory(serviceRegistry); } return sessionFactory; } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return buildSessionFactory(); } public static Session getSession() { Session hibernateSession = getSessionFactory().getCurrentSession(); return hibernateSession; } public static void shutdown() { getSessionFactory().close(); } } 

5.2.10决赛(新):

 public class HibernateUtil { private static StandardServiceRegistry registry; private static SessionFactory sessionFactory; public static SessionFactory getSessionFactory() { return buildSessionFactory(); } public static SessionFactory buildSessionFactory() { if (sessionFactory == null) { try { registry = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build(); MetadataSources sources = new MetadataSources(registry); Metadata metadata = sources.getMetadataBuilder().build(); sessionFactory = metadata.getSessionFactoryBuilder().build(); } catch (Exception e) { e.printStackTrace(); shutdown(); } } return sessionFactory; } public static Session getSession() { Session hibernateSession = getSessionFactory().getCurrentSession(); return hibernateSession; } public static void shutdown() { if (registry != null) { StandardServiceRegistryBuilder.destroy(registry); } } } 

现在我有一个方法,通过将DB表名称作为字符串传递来获取列名列表。 我之前在4.3.11.Final这样做过:

 public static List getColumnNames(String tableName) { List columnList=null; Map map = HibernateUtil.getSessionFactory().getAllClassMetadata(); Iterator<Entry> itr = map.entrySet().iterator(); while(itr.hasNext()){ ClassMetadata classMetaData = itr.next().getValue(); AbstractEntityPersister aep = (AbstractEntityPersister) classMetaData; if(aep.getTableName().split("\\.")[1].equalsIgnoreCase(tableName)){ columnList = new ArrayList(); String[] propertyNames = classMetaData.getPropertyNames(); for(String property : propertyNames){ try { PersistentClass persistentClass = HibernateUtil .getConfiguration().getClassMapping(classMetaData.getEntityName()); String clmName = ((Column) persistentClass.getProperty(property).getColumnIterator().next()).getName(); columnList.add(clmName); } catch(NoSuchElementException e){ log.error("Element not found idenfied as : "+property); } catch(Exception e){ log.error(e.getMessage()); } } break; } } return columnList; } 

现在升级后,它将方法getAllClassMetadata显示为已弃用,并且很难获得PersistentClass对象。 我在这里看到了类似的问题,但我无法弄清楚解决方案。 我必须更改当前代码的哪一部分,以使我的getColumnNames()方法完全像以前一样工作。 我提到了文档,它说要使用EntityManagerFactory.getMetamodel()但我找不到合适的参考例子。 我还要为此更改SessionFactory创建机制吗?

好问题。 事实上,我非常喜欢它,所以我写了一篇关于它的文章 。

首先,我们需要创建一个新的Integrator

 public class MetadataExtractorIntegrator implements org.hibernate.integrator.spi.Integrator { public static final MetadataExtractorIntegrator INSTANCE = new MetadataExtractorIntegrator(); private Database database; @Override public void integrate( Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { database = metadata.getDatabase(); } @Override public void disintegrate( SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { } public Database getDatabase() { return database; } } 

然后,我们可以配置Hibernate来使用它。

如果您正在使用Hibernate引导机制,那么您可以像这样添加它:

 final BootstrapServiceRegistryBuilder bsrb = new BootstrapServiceRegistryBuilder(); bsrb.enableAutoClose(); Integrator integrator = integrator(); if (integrator != null) { bsrb.applyIntegrator( integrator ); } final BootstrapServiceRegistry bsr = bsrb.build(); final StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder(bsr); 

如果你使用JPA进行自举,那么你可以按如下方式进行:

 protected EntityManagerFactory newEntityManagerFactory() { PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo( getClass().getSimpleName() ); Map configuration = new HashMap<>(); configuration.put("hibernate.integrator_provider", (IntegratorProvider) () -> Collections.singletonList( MetadataExtractorIntegrator.INSTANCE ) ); EntityManagerFactoryBuilderImpl entityManagerFactoryBuilder = new EntityManagerFactoryBuilderImpl( new PersistenceUnitInfoDescriptor(persistenceUnitInfo), configuration ); return entityManagerFactoryBuilder.build(); } 

现在,在运行以下测试时:

 for(Namespace namespace : MetadataExtractorIntegrator.INSTANCE .getDatabase() .getNamespaces()) { for( Table table : namespace.getTables()) { LOGGER.info( "Table {} has the following columns: {}", table, StreamSupport.stream( Spliterators.spliteratorUnknownSize( table.getColumnIterator(), Spliterator.ORDERED ), false ) .collect( Collectors.toList()) ); } } 

Hibernate输出日志中所有当前映射的表:

 Table org.hibernate.mapping.Table(post) has the following columns: [ org.hibernate.mapping.Column(id), org.hibernate.mapping.Column(title), org.hibernate.mapping.Column(version) ] Table org.hibernate.mapping.Table(post_comment) has the following columns: [ org.hibernate.mapping.Column(id), org.hibernate.mapping.Column(review), org.hibernate.mapping.Column(version), org.hibernate.mapping.Column(post_id) ] Table org.hibernate.mapping.Table(post_details) has the following columns: [ org.hibernate.mapping.Column(id), org.hibernate.mapping.Column(created_by), org.hibernate.mapping.Column(created_on), org.hibernate.mapping.Column(version) ] Table org.hibernate.mapping.Table(post_tag) has the following columns: [ org.hibernate.mapping.Column(post_id), org.hibernate.mapping.Column(tag_id) ] Table org.hibernate.mapping.Table(tag) has the following columns: [ org.hibernate.mapping.Column(id), org.hibernate.mapping.Column(name), org.hibernate.mapping.Column(version) ] 

而已!

最后我感谢弗拉德的文章。 我没有任何更改地采用了积分器代码,并修改了我的HibernateUtilgetColumns()方法。 所以这是我的代码:

SessionFactory创建:

 public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); public static SessionFactory getSessionFactory() { return buildSessionFactory(); } private static SessionFactory buildSessionFactory() { final BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().enableAutoClose() .applyIntegrator(MetadataExtractorIntegrator.INSTANCE).build(); final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder(bootstrapServiceRegistry).configure().build(); return new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory(); } public static Session getSession() { Session hibernateSession = getSessionFactory().getCurrentSession(); return hibernateSession; } public static void shutdown() { getSessionFactory().close(); } } 

元数据提取器(获取列名称):

 public static List getColumnNames(String tableName) { List columnList = new ArrayList<>(); for (Namespace namespace : MetadataExtractorIntegrator.INSTANCE.getDatabase().getNamespaces()) { for (Table table : namespace.getTables()) { if (table.getName().equalsIgnoreCase(lookupTableName)) { Iterator iterator = table.getColumnIterator(); while (iterator.hasNext()) { columnList.add(iterator.next().getName()); } break; } } if (!columnList.isEmpty()) break; } return columnList; } 

使用hibernate 5获取列名的更简单方法

 final AbstractEntityPersister classMetadata = (AbstractEntityPersister) sessionFactory.getClassMetadata(clazz) final String[] names = classMetadata.getPropertyColumnNames(property)