/* * Created on 26-Nov-2004 * */ package org.hibernate.cfg; import java.util.Iterator; import org.dom4j.Element; import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.boot.Metadata; import org.hibernate.boot.internal.ClassLoaderAccessImpl; import org.hibernate.boot.internal.InFlightMetadataCollectorImpl; import org.hibernate.boot.internal.MetadataBuilderImpl.MetadataBuildingOptionsImpl; import org.hibernate.boot.internal.MetadataBuildingContextRootImpl; import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.BasicTypeRegistration; import org.hibernate.boot.spi.ClassLoaderAccess; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingOptions; import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy; import org.hibernate.cfg.reveng.ReverseEngineeringStrategy; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.Mapping; import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Table; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.Type; import org.hibernate.type.TypeFactory; import org.hibernate.type.TypeResolver; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.UserType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author max * */ public class JDBCMetaDataConfiguration extends Configuration { private static final Logger log = LoggerFactory.getLogger(JDBCMetaDataConfiguration.class); private ReverseEngineeringStrategy revEngStrategy = new DefaultReverseEngineeringStrategy(); private StandardServiceRegistry serviceRegistry = null; private InFlightMetadataCollectorImpl metadataCollector; private ClassLoaderAccess classLoaderAccess = null; private MetadataBuildingOptions metadataBuildingOptions = null; private MetadataBuildingContext metadataBuildingContext = null; private Metadata metadata = null; public Metadata getMetadata() { if (metadata == null) { metadata = getMetadataCollector().buildMetadataInstance(getMetadataBuildingContext()); } return metadata; } private MetadataBuildingOptions getMetadataBuildingOptions() { if (metadataBuildingOptions == null) { metadataBuildingOptions = new MetadataBuildingOptionsImpl( getServiceRegistry() ); } return metadataBuildingOptions; } private ClassLoaderAccess getClassLoaderAccess() { if (classLoaderAccess == null) { MetadataBuildingOptions options = getMetadataBuildingOptions(); ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class ); classLoaderAccess = new ClassLoaderAccessImpl( options.getTempClassLoader(), classLoaderService ); } return classLoaderAccess; } private InFlightMetadataCollectorImpl getMetadataCollector() { if (metadataCollector == null) { MetadataBuildingOptions options = getMetadataBuildingOptions(); BasicTypeRegistry basicTypeRegistry = handleTypes( options ); metadataCollector = new InFlightMetadataCollectorImpl( options, new TypeResolver( basicTypeRegistry, new TypeFactory() ) ); } return metadataCollector; } private MetadataBuildingContext getMetadataBuildingContext() { if (metadataBuildingContext == null) { metadataBuildingContext = new MetadataBuildingContextRootImpl( getMetadataBuildingOptions(), getClassLoaderAccess(), getMetadataCollector()); } return metadataBuildingContext; } public StandardServiceRegistry getServiceRegistry(){ if(serviceRegistry == null){ serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(getProperties()) .build(); } return serviceRegistry; } public void readFromJDBC() { JDBCBinder binder = new JDBCBinder( getServiceRegistry(), getProperties(), getMetadataBuildingContext(), getReverseEngineeringStrategy(), preferBasicCompositeIds()); binder.readFromDatabase( null, null, buildMapping(getMetadata())); } @Override public SessionFactory buildSessionFactory() { return getMetadata().buildSessionFactory(); } static private Mapping buildMapping(final Metadata metadata) { return new Mapping() { /** * Returns the identifier type of a mapped class */ public Type getIdentifierType(String persistentClass) throws MappingException { final PersistentClass pc = metadata.getEntityBinding(persistentClass); if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); return pc.getIdentifier().getType(); } public String getIdentifierPropertyName(String persistentClass) throws MappingException { final PersistentClass pc = metadata.getEntityBinding(persistentClass); if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); if ( !pc.hasIdentifierProperty() ) return null; return pc.getIdentifierProperty().getName(); } public Type getReferencedPropertyType(String persistentClass, String propertyName) throws MappingException { final PersistentClass pc = metadata.getEntityBinding(persistentClass); if (pc==null) throw new MappingException("persistent class not known: " + persistentClass); Property prop = pc.getProperty(propertyName); if (prop==null) throw new MappingException("property not known: " + persistentClass + '.' + propertyName); return prop.getType(); } public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { return null; } }; } private boolean ignoreconfigxmlmapppings = true; // set to true and fk's that are part of a primary key will just be mapped as the raw value and as a readonly property. if false, it will be <many-to-one-key-property private boolean preferBasicCompositeIds = true; /** * If true, compositeid's will not create key-many-to-one and * non-updatable/non-insertable many-to-one will be created instead. * @return */ public boolean preferBasicCompositeIds() { return preferBasicCompositeIds ; } public void setPreferBasicCompositeIds(boolean flag) { preferBasicCompositeIds = flag; } protected void parseMappingElement(Element subelement, String name) { if(!ignoreconfigxmlmapppings ) { //FIXME the method is private // super.parseMappingElement(subelement, name); } else { log.info("Ignoring " + name + " mapping"); } } public void setReverseEngineeringStrategy(ReverseEngineeringStrategy reverseEngineeringStrategy) { this.revEngStrategy = reverseEngineeringStrategy; } public ReverseEngineeringStrategy getReverseEngineeringStrategy() { return revEngStrategy; } private static BasicTypeRegistry handleTypes(MetadataBuildingOptions options) { final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class ); // ultimately this needs to change a little bit to account for HHH-7792 final BasicTypeRegistry basicTypeRegistry = new BasicTypeRegistry(); final TypeContributions typeContributions = new TypeContributions() { public void contributeType(BasicType type) { basicTypeRegistry.register( type ); } public void contributeType(BasicType type, String... keys) { basicTypeRegistry.register( type, keys ); } public void contributeType(UserType type, String... keys) { basicTypeRegistry.register( type, keys ); } public void contributeType(CompositeUserType type, String... keys) { basicTypeRegistry.register( type, keys ); } }; // add Dialect contributed types final Dialect dialect = options.getServiceRegistry().getService( JdbcServices.class ).getDialect(); dialect.contributeTypes( typeContributions, options.getServiceRegistry() ); // add TypeContributor contributed types. for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) { contributor.contribute( typeContributions, options.getServiceRegistry() ); } // add explicit application registered types for ( BasicTypeRegistration basicTypeRegistration : options.getBasicTypeRegistrations() ) { basicTypeRegistry.register( basicTypeRegistration.getBasicType(), basicTypeRegistration.getRegistrationKeys() ); } return basicTypeRegistry; } public Table getTable(String tabName) { if (getMetadata() != null) { Iterator<Table> iter = getMetadata().collectTableMappings().iterator(); while (iter.hasNext()) { Table table = (Table) iter.next(); if (table.getName().equals(tabName)) { return table; } } } return null; } }