Create clause SELECT from metadata for batch (for confirmation)

Hi,

For create clause SELECT from metadata for batch, i implemented this class.
For you the method createSelectRequest is correct ?

Below I put the unit test for the example.

Thank you ?

package com.efluid.hibernate.dao;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value;

import com.imrglobal.framework.businessObject.BusinessObject;

import com.efluid.hibernate.config.HibernateProperties;
import com.efluid.hibernate.integrator.TransientIntegrator;

/**
 * Permet de récupérer le getSelectRequest à l'identique des DAOs du framework.
 */
public final class HibernateDAOService {

  private static final HibernateDAOService INSTANCE = new HibernateDAOService();
  private static final String SEPARATEUR = "::";

  /**
   * Clé : [NomClasse]::[NomTable]
   * Valeur : [Colonnes]
   */
  private static final Map<String, String> selectRequest = new ConcurrentHashMap<>();

  public static HibernateDAOService getInstance() {
    return INSTANCE;
  }

  /**
   * Permet de récupérer le getSelectRequest comme avec les DAO du framework.
   */
  public String getSelectRequest(Class<? extends BusinessObject> classe, String table) {
    return selectRequest.computeIfAbsent(classe.getName() + SEPARATEUR + table, k -> createSelectRequest(classe, table));
  }

  private String createSelectRequest(Class<? extends BusinessObject> classe, String table) {
    MetadataSources metadataSources = new MetadataSources(getStandardServiceRegistry());
    metadataSources.addAnnotatedClass(classe);
    Metadata metadata = metadataSources.buildMetadata();

    new TransientIntegrator().integrate(metadata, (BootstrapContext) null, null);

    PersistentClass entityBinding = metadata.getEntityBinding(classe.getName());
    List<Property> properties = entityBinding.getProperties();

    return getColonneID(entityBinding, table) +
        getColonneDiscriminator(entityBinding, table) +
        getColonnesAttributs(table, properties);
  }

  private StandardServiceRegistry getStandardServiceRegistry() {
    return new StandardServiceRegistryBuilder()
        .applySettings(HibernateProperties.getParametres())
        .build();
  }

  private static String getColonneID(PersistentClass entityBinding, String table) {
    Column colonne = entityBinding.getKey().getColumns().get(0);
    return table.equalsIgnoreCase(colonne.getValue().getTable().getName()) ? colonne.getName() + "," : "";
  }

  private static String getColonneDiscriminator(PersistentClass entityBinding, String table) {
    Value discriminator = entityBinding.getDiscriminator();
    if (discriminator == null || discriminator.hasFormula()) {
      return "";
    }
    Column column = discriminator.getColumns().get(0);
    return table.equalsIgnoreCase(column.getValue().getTable().getName()) ? column.getName() + "," : "";
  }

  private static String getColonnesAttributs(final String table, final List<Property> properties) {
    return properties.stream().map(Property::getValue)
                     .flatMap(value -> value.getColumns().stream())
                     .filter(isTable(table))
                     .map(Column::getName)
                     .collect(Collectors.joining(","));
  }

  private static Predicate<Column> isTable(final String table) {
    return column -> table.equalsIgnoreCase(column.getValue().getTable().getName());
  }
}
package com.efluid.hibernate.dao;

import static org.assertj.core.api.Assertions.assertThat;

import static com.efluid.hibernate.integrator.GroupeAttributs.*;

import java.sql.Timestamp;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.SecondaryTable;
import jakarta.persistence.Table;

import org.hibernate.annotations.Any;
import org.hibernate.annotations.AnyDiscriminatorValue;
import org.hibernate.annotations.AnyKeyJavaClass;
import org.junit.jupiter.api.Test;

import com.efluid.hibernate.integrator.AttributsTransient;
import com.hermes.arc.commun.businessobject.HermesBusinessObject;

/**
 * Test {@link HibernateDAOService}.
 */
public class TestITHibernateDAOService {

  @Test
  public void doit_retourner_le_get_select_request() {
    assertThat(HibernateDAOService.getInstance().getSelectRequest(ObjetSelectRequest.class, "table")).isEqualTo("ID,ROLE,AGENCE,ANY_ROLE,ANY_ID,DATE,NOM,NOMBRE,REFTO_ID");
    assertThat(HibernateDAOService.getInstance().getSelectRequest(ObjetSelectRequest.class, "table2")).isEqualTo("NOMTABLE2");
  }

  @Entity
  @Table(name = "table")
  @SecondaryTable(name = "table2")
  @DiscriminatorColumn(name = "ROLE")
  @DiscriminatorValue("OK")
  @AttributsTransient(groupesAttributs = { ACTEURS_TECHNIQUES, CONFIDENTIALITE, SUPPRESSION_LOGIQUE })
  public static class ObjetSelectRequest extends HermesBusinessObject {

    private Timestamp date;
    private int nombre;
    private String nom;
    @Column(table = "table2")
    private String nomTable2;

    @OneToOne
    private ObjetSelectRequest refTo;

    @Any
    @AnyKeyJavaClass(String.class)
    @AnyDiscriminatorValue(discriminator = "objet", entity = ObjetSelectRequest.class)
    @JoinColumn(name = "ANY_ID")
    @Column(name = "ANY_ROLE")
    private ObjetSelectRequest any;
  }
}

It looks ok to me, but you really shouldn’t mess with the boot model unless you know what you are doing.

Thank for your reponse.

The problem it’s that i haven’t got access to metadata but only metamodel with the session factory.

Our session factory :

public class EfluidSessionFactory {

  public static final EfluidSessionFactory INSTANCE = new EfluidSessionFactory();
  private SessionFactory sessionFactory;

  private EfluidSessionFactory() {}

  public MappingMetamodel getMetaModel() {
    return (MappingMetamodel) getSessionFactory().getMetamodel();
  }

  public SessionFactory getSessionFactory() {
    return getFactory();
  }

  private SessionFactory getFactory() {
    if (sessionFactory == null) {
      initialiserSessionFactory();
    }
    return sessionFactory;
  }

  private synchronized void initialiserSessionFactory() {
    if (sessionFactory == null) {
      sessionFactory = instancierEntityManagerFactoryBuilder(null).build().unwrap(SessionFactory.class);
    }
  }

  public EntityManagerFactoryBuilder instancierEntityManagerFactoryBuilder(Map<String, String> settings) {
    return Bootstrap.getEntityManagerFactoryBuilder(new EfluidPersistenceUnitInfo(), settings, (ClassLoader) null);
  }
}