2017-04-25 4 views
5

Je suis en train de mettre à jour ma version d'Hibernate vers la dernière version 5.2.10. J'ai remplacé mon code dans HibernateUtil pour la création de SessionFactory.Mise à niveau d'Hibernate vers la version 5.2 - Création de Session Factory et remplacement de PersistentClass pour obtenir les propriétés de classe d'entité

4.3.11.Final (Précédent):

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 finale (Nouveau):

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); 
    } 
    } 
} 

Maintenant, j'ai une méthode qui me chercher la liste des noms de colonnes en transmettant le nom de la table DB en tant que chaîne. Je l'ai fait comme ça avant dans 4.3.11.Final:

public static List<String> getColumnNames(String tableName) { 

     List<String> columnList=null; 

     Map<String, ClassMetadata> map = HibernateUtil.getSessionFactory().getAllClassMetadata(); 
     Iterator<Entry<String, ClassMetadata>> 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>(); 
       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; 
    } 

Maintenant, après la mise à niveau, il montre la méthode getAllClassMetadata comme dépréciée et je suis face à la difficulté d'obtenir l'objet PersistentClass. J'ai vu une question similaire here mais je ne pouvais pas comprendre exactement la solution. Quelle partie de mon code actuel dois-je changer pour que ma méthode getColumnNames() fonctionne exactement comme avant? J'ai référé la documentation et il dit d'utiliser le EntityManagerFactory.getMetamodel() à la place, mais je ne peux pas trouver des exemples de référence appropriés de la même chose. Aussi dois-je changer le mécanisme de création de SessionFactory pour cela?

Répondre

2

Enfin, je l'ai fait merci à l'article de Vlad. J'ai pris le code de l'intégrateur sans aucun changement et j'ai modifié mon HibernateUtil et la méthode getColumns(). Alors, voici mon code:

création 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(); 
    } 
} 

métadonnées Extractor (obtenir les noms de colonnes):

public static List<String> getColumnNames(String tableName) { 

    List<String> columnList = new ArrayList<>(); 

    for (Namespace namespace : MetadataExtractorIntegrator.INSTANCE.getDatabase().getNamespaces()) { 
     for (Table table : namespace.getTables()) { 
      if (table.getName().equalsIgnoreCase(lookupTableName)) { 
       Iterator<Column> iterator = table.getColumnIterator(); 
       while (iterator.hasNext()) { 
        columnList.add(iterator.next().getName()); 
       } 
       break; 
      } 
     } 
     if (!columnList.isEmpty()) 
      break; 
    } 
    return columnList; 
} 
2

Bonne question. En fait, je l'ai tellement aimé que j'ai écrit an article about it.

D'abord, nous devons créer un nouveau 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; 
    } 
} 

Ensuite, nous pouvons simplement configurer Hibernate pour l'utiliser.

Si vous utilisez le mécanisme d'amorçage Hibernate, vous pouvez l'ajouter comme ceci:

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); 

Si vous bootstrapping avec JPA, vous pouvez le faire comme suit:

protected EntityManagerFactory newEntityManagerFactory() { 
    PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(
     getClass().getSimpleName() 
    ); 

    Map<String, Object> configuration = new HashMap<>(); 


    configuration.put("hibernate.integrator_provider", 
     (IntegratorProvider)() -> Collections.singletonList(MetadataExtractorIntegrator.INSTANCE) 
    ); 

    EntityManagerFactoryBuilderImpl entityManagerFactoryBuilder = new EntityManagerFactoryBuilderImpl(
      new PersistenceUnitInfoDescriptor(persistenceUnitInfo), configuration 
    ); 
    return entityManagerFactoryBuilder.build(); 
} 

maintenant, lors du test suivant:

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()) 
     ); 
    } 
} 

sorties Hibernate tous les t actuellement cartographiée ables dans le journal:

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) 
] 

C'est tout!

+0

Merci @Vlad pour votre réponse.Alors devrais-je remplacer mon code de classe HibernateUtil que j'ai mentionné ci-dessus avec le mécanisme de bootstrap Hibernate que vous avez suggéré? Aussi pouvez-vous expliquer un peu plus à ce sujet car ce mécanisme est relativement nouveau pour moi. Comment lit-il la configuration en tant que pas de hibernate.cfg.xml dans votre code? La ligne integrator integrator = integrator() fait référence à quelle méthode d'intégrateur? Toujours dans la méthode de test, namespace.getTables(), fait partie de org.hibernate.boot.relational.Namespace. Aussi comment puis-je obtenir le nom de la colonne? –

+0

Découvrez [cet article] (https://vladmihalcea.com/2017/05/02/how-to-get-access-to-database-table-metadata-with-hibernate-5/) pour voir que vous pouvez avoir accès aux colonnes aussi. Vous pouvez bifurquer [mon livre, Java Persistence à haute performance, référentiel GitHub] (https://github.com/vladmihalcea/high-performance-java-persistence/blob/master/core/src/test/java/com/vladmihalcea /book/hpjp/hibernate/metadata/MetadataTest.java) pour voir comment cela fonctionne, ainsi que le bootstrap. –