* HBM mappings
* dynamic models * initial non-aggregated cid support
This commit is contained in:
parent
593eeb0d9f
commit
96f4a350e0
|
@ -94,4 +94,12 @@
|
|||
|90005500
|
||||
|org.hibernate.sql.ast.tree.SqlAstTreeLogger
|
||||
|
||||
|90005501
|
||||
|90005600
|
||||
|org.hibernate.boot.jaxb.JaxbLogger
|
||||
|
||||
|90005601
|
||||
|90005700
|
||||
|org.hibernate.envers.boot.EnversBootLogger
|
||||
|
||||
|===
|
||||
|
|
|
@ -32,7 +32,9 @@ import org.hibernate.boot.jaxb.SourceType;
|
|||
import org.hibernate.boot.jaxb.internal.CacheableFileXmlSource;
|
||||
import org.hibernate.boot.jaxb.internal.JarFileEntryXmlSource;
|
||||
import org.hibernate.boot.jaxb.internal.JaxpSourceXmlSource;
|
||||
import org.hibernate.boot.jaxb.internal.XmlSources;
|
||||
import org.hibernate.boot.jaxb.spi.Binding;
|
||||
import org.hibernate.boot.jaxb.spi.XmlSource;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistry;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
|
@ -59,10 +61,11 @@ public class MetadataSources implements Serializable {
|
|||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( MetadataSources.class );
|
||||
|
||||
private final ServiceRegistry serviceRegistry;
|
||||
private final ClassLoaderService classLoaderService;
|
||||
|
||||
private XmlMappingBinderAccess xmlMappingBinderAccess;
|
||||
|
||||
private List<Binding> xmlBindings;
|
||||
private List<Binding<?>> xmlBindings;
|
||||
private LinkedHashSet<Class<?>> annotatedClasses;
|
||||
private LinkedHashSet<String> annotatedClassNames;
|
||||
private LinkedHashSet<String> annotatedPackages;
|
||||
|
@ -90,11 +93,12 @@ public class MetadataSources implements Serializable {
|
|||
}
|
||||
}
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
}
|
||||
|
||||
protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) {
|
||||
return BootstrapServiceRegistry.class.isInstance( serviceRegistry )
|
||||
|| StandardServiceRegistry.class.isInstance( serviceRegistry );
|
||||
return serviceRegistry instanceof BootstrapServiceRegistry
|
||||
|| serviceRegistry instanceof StandardServiceRegistry;
|
||||
}
|
||||
|
||||
public XmlMappingBinderAccess getXmlMappingBinderAccess() {
|
||||
|
@ -104,7 +108,7 @@ public class MetadataSources implements Serializable {
|
|||
return xmlMappingBinderAccess;
|
||||
}
|
||||
|
||||
public List<Binding> getXmlBindings() {
|
||||
public List<Binding<?>> getXmlBindings() {
|
||||
return xmlBindings == null ? Collections.emptyList() : xmlBindings;
|
||||
}
|
||||
|
||||
|
@ -332,7 +336,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addResource(String name) {
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( name ) );
|
||||
final XmlSource xmlSource = XmlSources.fromResource( name, classLoaderService );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -358,7 +364,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addFile(File file) {
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( file ) );
|
||||
final XmlSource xmlSource = XmlSources.fromFile( file );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -372,15 +380,10 @@ public class MetadataSources implements Serializable {
|
|||
* @see #addCacheableFile(java.io.File)
|
||||
*/
|
||||
public MetadataSources addCacheableFile(String path) {
|
||||
final Origin origin = new Origin( SourceType.FILE, path );
|
||||
addCacheableFile( origin, new File( path ) );
|
||||
addCacheableFile( new File( path ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addCacheableFile(Origin origin, File file) {
|
||||
getXmlBindingsForWrite().add( new CacheableFileXmlSource( origin, file, false ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cached mapping file. A cached file is a serialized representation of the DOM structure of a
|
||||
* particular mapping. It is saved from a previous call as a file with the name {@code {xmlFile}.bin}
|
||||
|
@ -395,8 +398,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addCacheableFile(File file) {
|
||||
final Origin origin = new Origin( SourceType.FILE, file.getName() );
|
||||
addCacheableFile( origin, file );
|
||||
final XmlSource xmlSource = XmlSources.fromCacheableFile( file );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -413,9 +417,10 @@ public class MetadataSources implements Serializable {
|
|||
* @throws org.hibernate.type.SerializationException Indicates a problem deserializing the cached dom tree
|
||||
* @throws java.io.FileNotFoundException Indicates that the cached file was not found or was not usable.
|
||||
*/
|
||||
public MetadataSources addCacheableFileStrictly(File file) throws SerializationException, FileNotFoundException {
|
||||
final Origin origin = new Origin( SourceType.FILE, file.getAbsolutePath() );
|
||||
getXmlBindingsForWrite().add( new CacheableFileXmlSource( origin, file, true ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
public MetadataSources addCacheableFileStrictly(File file) throws SerializationException {
|
||||
final XmlSource xmlSource = XmlSources.fromCacheableFile( file, true );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -427,7 +432,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addInputStream(InputStreamAccess xmlInputStreamAccess) {
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( xmlInputStreamAccess ) );
|
||||
final XmlSource xmlSource = XmlSources.fromStream( xmlInputStreamAccess );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -439,7 +446,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addInputStream(InputStream xmlInputStream) {
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( xmlInputStream ) );
|
||||
final XmlSource xmlSource = XmlSources.fromStream( xmlInputStream );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -451,7 +460,9 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addURL(URL url) {
|
||||
getXmlBindingsForWrite().add( getXmlMappingBinderAccess().bind( url ) );
|
||||
final XmlSource xmlSource = XmlSources.fromUrl( url );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -466,8 +477,9 @@ public class MetadataSources implements Serializable {
|
|||
*/
|
||||
@Deprecated
|
||||
public MetadataSources addDocument(Document document) {
|
||||
final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH );
|
||||
getXmlBindingsForWrite().add( new JaxpSourceXmlSource( origin, new DOMSource( document ) ).doBind( getXmlMappingBinderAccess().getMappingBinder() ) );
|
||||
final XmlSource xmlSource = XmlSources.fromDocument( document );
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -481,42 +493,15 @@ public class MetadataSources implements Serializable {
|
|||
* @return this (for method chaining purposes)
|
||||
*/
|
||||
public MetadataSources addJar(File jar) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Seeking mapping documents in jar file : %s", jar.getName() );
|
||||
}
|
||||
final Origin origin = new Origin( SourceType.JAR, jar.getAbsolutePath() );
|
||||
try {
|
||||
JarFile jarFile = new JarFile( jar );
|
||||
final boolean TRACE = LOG.isTraceEnabled();
|
||||
try {
|
||||
Enumeration jarEntries = jarFile.entries();
|
||||
while ( jarEntries.hasMoreElements() ) {
|
||||
final ZipEntry zipEntry = (ZipEntry) jarEntries.nextElement();
|
||||
if ( zipEntry.getName().endsWith( ".hbm.xml" ) ) {
|
||||
if ( TRACE ) {
|
||||
LOG.tracef( "found mapping document : %s", zipEntry.getName() );
|
||||
}
|
||||
getXmlBindingsForWrite().add(
|
||||
new JarFileEntryXmlSource( origin, jarFile, zipEntry ).doBind( getXmlMappingBinderAccess().getMappingBinder() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
jarFile.close();
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( IOException e ) {
|
||||
throw new MappingNotFoundException( e, origin );
|
||||
}
|
||||
final XmlMappingBinderAccess binderAccess = getXmlMappingBinderAccess();
|
||||
XmlSources.fromJar(
|
||||
jar,
|
||||
xmlSource -> getXmlBindingsForWrite().add( xmlSource.doBind( binderAccess.getMappingBinder() ) )
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
private <Binding> List getXmlBindingsForWrite() {
|
||||
private List<Binding<?>> getXmlBindingsForWrite() {
|
||||
if ( xmlBindings == null ) {
|
||||
xmlBindings = new ArrayList<>();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.boot.archive.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Contract for building InputStreams, especially in on-demand situations
|
||||
|
@ -19,12 +21,26 @@ public interface InputStreamAccess {
|
|||
*
|
||||
* @return The backing resource name
|
||||
*/
|
||||
public String getStreamName();
|
||||
String getStreamName();
|
||||
|
||||
/**
|
||||
* Get access to the stream. Can be called multiple times, a different stream instance should be returned each time.
|
||||
*
|
||||
* @return The stream
|
||||
*/
|
||||
public InputStream accessInputStream();
|
||||
InputStream accessInputStream();
|
||||
|
||||
default <X> X fromStream(Function<InputStream, X> action) {
|
||||
final InputStream inputStream = accessInputStream();
|
||||
try {
|
||||
return action.apply( inputStream );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,18 +54,17 @@ public class BootstrapContextImpl implements BootstrapContext {
|
|||
private static final Logger log = Logger.getLogger( BootstrapContextImpl.class );
|
||||
|
||||
private final StandardServiceRegistry serviceRegistry;
|
||||
|
||||
private final MutableJpaCompliance jpaCompliance;
|
||||
private final MetadataBuildingOptions metadataBuildingOptions;
|
||||
|
||||
private final TypeConfiguration typeConfiguration;
|
||||
private final MutableJpaCompliance jpaCompliance;
|
||||
|
||||
private final ClassLoaderAccessImpl classLoaderAccess;
|
||||
|
||||
private boolean isJpaBootstrap;
|
||||
|
||||
private final JavaReflectionManager hcannReflectionManager;
|
||||
private final ClassmateContext classmateContext;
|
||||
private final MetadataBuildingOptions metadataBuildingOptions;
|
||||
|
||||
private boolean isJpaBootstrap;
|
||||
|
||||
private ScanOptions scanOptions;
|
||||
private ScanEnvironment scanEnvironment;
|
||||
|
@ -76,7 +75,7 @@ public class BootstrapContextImpl implements BootstrapContext {
|
|||
|
||||
private HashMap<String,SqmFunctionDescriptor> sqlFunctionMap;
|
||||
private ArrayList<AuxiliaryDatabaseObject> auxiliaryDatabaseObjectList;
|
||||
private HashMap<Class, ConverterDescriptor> attributeConverterDescriptorMap;
|
||||
private HashMap<Class<?>, ConverterDescriptor> attributeConverterDescriptorMap;
|
||||
private ArrayList<CacheRegionDefinition> cacheRegionDefinitions;
|
||||
private ManagedTypeRepresentationResolver representationStrategySelector;
|
||||
|
||||
|
@ -87,8 +86,7 @@ public class BootstrapContextImpl implements BootstrapContext {
|
|||
this.classmateContext = new ClassmateContext();
|
||||
this.metadataBuildingOptions = metadataBuildingOptions;
|
||||
|
||||
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
this.classLoaderAccess = new ClassLoaderAccessImpl( classLoaderService );
|
||||
this.classLoaderAccess = new ClassLoaderAccessImpl( serviceRegistry.getService( ClassLoaderService.class ) );
|
||||
this.hcannReflectionManager = generateHcannReflectionManager();
|
||||
|
||||
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.jaxb;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
@ValidIdRange( min = 90005501, max = 90005600 )
|
||||
public interface JaxbLogger extends BasicLogger {
|
||||
String LOGGER_NAME = "org.hibernate.orm.boot.jaxb";
|
||||
|
||||
JaxbLogger JAXB_LOGGER = Logger.getMessageLogger(
|
||||
JaxbLogger.class,
|
||||
LOGGER_NAME
|
||||
);
|
||||
|
||||
boolean TRACE_ENABLED = JAXB_LOGGER.isTraceEnabled();
|
||||
boolean DEBUG_ENABLED = JAXB_LOGGER.isDebugEnabled();
|
||||
}
|
|
@ -37,6 +37,7 @@ public abstract class AbstractBinder implements Binder {
|
|||
private final LocalXmlResourceResolver xmlResourceResolver;
|
||||
private final boolean validateXml;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected AbstractBinder(ClassLoaderService classLoaderService) {
|
||||
this( classLoaderService, true );
|
||||
}
|
||||
|
@ -121,7 +122,6 @@ public abstract class AbstractBinder implements Binder {
|
|||
return staxFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "UnnecessaryLocalVariable" })
|
||||
private XMLInputFactory buildStaxFactory() {
|
||||
XMLInputFactory staxFactory = XMLInputFactory.newInstance();
|
||||
staxFactory.setXMLResolver( xmlResourceResolver );
|
||||
|
@ -150,6 +150,7 @@ public abstract class AbstractBinder implements Binder {
|
|||
|
||||
protected abstract Binding doBind(XMLEventReader staxEventReader, StartElement rootElementStartEvent, Origin origin);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected static boolean hasNamespace(StartElement startElement) {
|
||||
return ! "".equals( startElement.getName().getNamespaceURI() );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.jaxb.internal;
|
||||
|
||||
import org.hibernate.boot.archive.spi.InputStreamAccess;
|
||||
import org.hibernate.boot.jaxb.Origin;
|
||||
import org.hibernate.boot.jaxb.spi.Binder;
|
||||
import org.hibernate.boot.jaxb.spi.Binding;
|
||||
import org.hibernate.boot.jaxb.spi.XmlSource;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class InputStreamAccessXmlSource extends XmlSource {
|
||||
private final InputStreamAccess inputStreamAccess;
|
||||
|
||||
public InputStreamAccessXmlSource(Origin origin, InputStreamAccess inputStreamAccess) {
|
||||
super( origin );
|
||||
this.inputStreamAccess = inputStreamAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Binding doBind(Binder binder) {
|
||||
return doBind( binder, inputStreamAccess, getOrigin() );
|
||||
}
|
||||
|
||||
public static Binding doBind(Binder binder, InputStreamAccess inputStreamAccess, Origin origin) {
|
||||
return inputStreamAccess.fromStream(
|
||||
inputStream -> binder.bind( inputStream, origin )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ public class MappingBinder extends AbstractBinder {
|
|||
|
||||
private JAXBContext hbmJaxbContext;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public MappingBinder(ClassLoaderService classLoaderService) {
|
||||
this( classLoaderService, true );
|
||||
}
|
||||
|
@ -50,7 +51,7 @@ public class MappingBinder extends AbstractBinder {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Binding doBind(
|
||||
protected Binding<?> doBind(
|
||||
XMLEventReader staxEventReader,
|
||||
StartElement rootElementStartEvent,
|
||||
Origin origin) {
|
||||
|
@ -98,7 +99,7 @@ public class MappingBinder extends AbstractBinder {
|
|||
// are trying to read has comments this process will blow up. So we
|
||||
// override that to add that support as best we can
|
||||
XMLEvent event = reader.peek();
|
||||
if ( javax.xml.stream.events.Comment.class.isInstance( event ) ) {
|
||||
if ( event instanceof javax.xml.stream.events.Comment ) {
|
||||
return super.readComment( reader );
|
||||
}
|
||||
return super.readNode( reader );
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.net.UnknownHostException;
|
|||
import org.hibernate.boot.MappingException;
|
||||
import org.hibernate.boot.MappingNotFoundException;
|
||||
import org.hibernate.boot.jaxb.Origin;
|
||||
import org.hibernate.boot.jaxb.SourceType;
|
||||
import org.hibernate.boot.jaxb.spi.Binder;
|
||||
import org.hibernate.boot.jaxb.spi.Binding;
|
||||
import org.hibernate.boot.jaxb.spi.XmlSource;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.boot.jaxb.spi.XmlSource;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UrlXmlSource extends XmlSource {
|
||||
|
||||
private final URL url;
|
||||
|
||||
public UrlXmlSource(Origin origin, URL url) {
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.jaxb.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.hibernate.boot.MappingNotFoundException;
|
||||
import org.hibernate.boot.archive.spi.InputStreamAccess;
|
||||
import org.hibernate.boot.jaxb.JaxbLogger;
|
||||
import org.hibernate.boot.jaxb.Origin;
|
||||
import org.hibernate.boot.jaxb.SourceType;
|
||||
import org.hibernate.boot.jaxb.spi.XmlSource;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* Helper for building and handling {@link org.hibernate.boot.jaxb.spi.XmlSource} references
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class XmlSources {
|
||||
/**
|
||||
* Create an {@link XmlSource} from a named resource
|
||||
*/
|
||||
public static XmlSource fromResource(String resourceName, ClassLoaderService classLoaderService) {
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "reading mappings from resource : %s", resourceName );
|
||||
|
||||
final Origin origin = new Origin( SourceType.RESOURCE, resourceName );
|
||||
final URL url = classLoaderService.locateResource( resourceName );
|
||||
if ( url == null ) {
|
||||
throw new MappingNotFoundException( origin );
|
||||
}
|
||||
|
||||
return new UrlXmlSource( origin, url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link XmlSource} from a URL
|
||||
*/
|
||||
public static XmlSource fromUrl(URL url) {
|
||||
final String urlExternalForm = url.toExternalForm();
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "Reading mapping document from URL : %s", urlExternalForm );
|
||||
|
||||
final Origin origin = new Origin( SourceType.URL, urlExternalForm );
|
||||
return new UrlXmlSource( origin, url );
|
||||
}
|
||||
|
||||
public static XmlSource fromFile(File file) {
|
||||
final String filePath = file.getPath();
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "reading mappings from file : %s", filePath );
|
||||
|
||||
final Origin origin = new Origin( SourceType.FILE, filePath );
|
||||
|
||||
if ( !file.exists() ) {
|
||||
throw new MappingNotFoundException( origin );
|
||||
}
|
||||
|
||||
return new FileXmlSource( origin, file );
|
||||
}
|
||||
|
||||
public static XmlSource fromCacheableFile(File file) {
|
||||
return fromCacheableFile( file, false );
|
||||
}
|
||||
|
||||
public static XmlSource fromCacheableFile(File file, boolean strict) {
|
||||
final String filePath = file.getPath();
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "reading mappings from cacheable-file : %s", filePath );
|
||||
|
||||
final Origin origin = new Origin( SourceType.FILE, filePath );
|
||||
return new CacheableFileXmlSource( origin, file, true );
|
||||
}
|
||||
|
||||
public static XmlSource fromStream(InputStreamAccess inputStreamAccess) {
|
||||
final String streamName = inputStreamAccess.getStreamName();
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "reading mappings from InputStreamAccess : %s", streamName );
|
||||
|
||||
final Origin origin = new Origin( SourceType.INPUT_STREAM, streamName );
|
||||
return new InputStreamAccessXmlSource( origin, inputStreamAccess );
|
||||
}
|
||||
|
||||
public static XmlSource fromStream(InputStream inputStream) {
|
||||
JaxbLogger.JAXB_LOGGER.trace( "reading mappings from InputStream" );
|
||||
|
||||
final Origin origin = new Origin( SourceType.INPUT_STREAM, null );
|
||||
return new InputStreamXmlSource( origin, inputStream, false );
|
||||
}
|
||||
|
||||
public static XmlSource fromDocument(Document document) {
|
||||
JaxbLogger.JAXB_LOGGER.trace( "reading mappings from DOM" );
|
||||
final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH );
|
||||
return new JaxpSourceXmlSource( origin, new DOMSource( document ) );
|
||||
}
|
||||
|
||||
public static void fromJar(File jar, Consumer<XmlSource> consumer) {
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "Seeking mapping documents in jar file : %s", jar.getName() );
|
||||
|
||||
final Origin origin = new Origin( SourceType.JAR, jar.getAbsolutePath() );
|
||||
|
||||
try {
|
||||
final JarFile jarFile = new JarFile( jar );
|
||||
|
||||
try {
|
||||
final Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while ( entries.hasMoreElements() ) {
|
||||
final JarEntry jarEntry = entries.nextElement();
|
||||
if ( jarEntry.getName().endsWith( ".hbm.xml" ) ) {
|
||||
JaxbLogger.JAXB_LOGGER.tracef( "Found hbm.xml mapping in jar : %s", jarEntry.getName() );
|
||||
consumer.accept( new JarFileEntryXmlSource( origin, jarFile, jarEntry ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
jarFile.close();
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( IOException e ) {
|
||||
throw new MappingNotFoundException( e, origin );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -91,14 +91,29 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
|
|||
else {
|
||||
// if we get here, we should have a composite identifier. Just need
|
||||
// to determine if it is aggregated, or non-aggregated...
|
||||
if ( StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getName() ) ) {
|
||||
if ( rootEntitySource.jaxbEntityMapping().getCompositeId().isMapped()
|
||||
&& StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getClazz() ) ) {
|
||||
|
||||
if ( rootEntitySource.jaxbEntityMapping().getCompositeId().isMapped() ) {
|
||||
if ( StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getClazz() ) ) {
|
||||
throw new MappingException(
|
||||
"mapped composite identifier must name component class to use.",
|
||||
rootEntitySource.origin()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getClazz() ) ) {
|
||||
if ( StringHelper.isEmpty( rootEntitySource.jaxbEntityMapping().getCompositeId().getName() ) ) {
|
||||
throw new MappingException(
|
||||
"dynamic composite-id must specify name",
|
||||
rootEntitySource.origin()
|
||||
);
|
||||
}
|
||||
|
||||
// we have a non-aggregated id without an IdClass
|
||||
return new IdentifierSourceNonAggregatedCompositeImpl( rootEntitySource );
|
||||
}
|
||||
else if ( rootEntitySource.jaxbEntityMapping().getCompositeId().isMapped() ) {
|
||||
// we have a non-aggregated id with an IdClass
|
||||
return new IdentifierSourceNonAggregatedCompositeImpl( rootEntitySource );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -9,6 +9,9 @@ package org.hibernate.boot.spi;
|
|||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.boot.CacheRegionDefinition;
|
||||
|
@ -162,6 +165,8 @@ public interface BootstrapContext {
|
|||
*/
|
||||
Collection<CacheRegionDefinition> getCacheRegionDefinitions();
|
||||
|
||||
ManagedTypeRepresentationResolver getRepresentationStrategySelector();
|
||||
|
||||
/**
|
||||
* Releases the "bootstrap only" resources held by this BootstrapContext.
|
||||
* <p/>
|
||||
|
@ -172,6 +177,4 @@ public interface BootstrapContext {
|
|||
* @todo verify this ^^
|
||||
*/
|
||||
void release();
|
||||
|
||||
ManagedTypeRepresentationResolver getRepresentationStrategySelector();
|
||||
}
|
||||
|
|
|
@ -21,16 +21,18 @@ import javax.persistence.metamodel.SingularAttribute;
|
|||
import javax.persistence.metamodel.Type;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.internal.HEMLogging;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.KeyValue;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
|
@ -43,10 +45,9 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl;
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -358,7 +359,7 @@ public class MetadataContext {
|
|||
// 2) register the part (mapping role)
|
||||
// 3) somehow get the mapping role "into" the part (setter, ?)
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<?> identifiableType) {
|
||||
if ( persistentClass.hasIdentifierProperty() ) {
|
||||
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
|
||||
|
@ -371,31 +372,38 @@ public class MetadataContext {
|
|||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyIdAttribute( idAttribute );
|
||||
}
|
||||
}
|
||||
else if ( persistentClass.hasIdentifierMapper() ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Iterator<Property> propertyIterator = persistentClass.getIdentifierMapper().getPropertyIterator();
|
||||
final Set<SingularPersistentAttribute<?, ?>> idClassAttributes = (Set<SingularPersistentAttribute<?, ?>>) buildIdClassAttributes(
|
||||
identifiableType,
|
||||
propertyIterator
|
||||
);
|
||||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyIdClassAttributes( idClassAttributes );
|
||||
}
|
||||
else {
|
||||
final KeyValue value = persistentClass.getIdentifier();
|
||||
if ( value instanceof Component ) {
|
||||
final Component component = (Component) value;
|
||||
if ( component.getPropertySpan() > 1 ) {
|
||||
//FIXME we are an Hibernate embedded id (ie not type)
|
||||
}
|
||||
else {
|
||||
//FIXME take care of declared vs non declared property
|
||||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyIdAttribute(
|
||||
attributeFactory.buildIdAttribute(
|
||||
identifiableType,
|
||||
(Property) component.getPropertyIterator().next()
|
||||
)
|
||||
);
|
||||
}
|
||||
// we have a non-aggregated composite-id
|
||||
|
||||
//noinspection RedundantClassCall
|
||||
if ( ! Component.class.isInstance( persistentClass.getIdentifier() ) ) {
|
||||
throw new MappingException( "Expecting Component for id mapping with no id-attribute" );
|
||||
}
|
||||
|
||||
// Handle the actual id-attributes
|
||||
final Component cidValue = (Component) persistentClass.getIdentifier();
|
||||
final Iterator<Property> cidPropertyItr = cidValue.getPropertyIterator();
|
||||
final Set<SingularPersistentAttribute<?,?>> idAttributes = new HashSet<>( cidValue.getPropertySpan() );
|
||||
|
||||
while ( cidPropertyItr.hasNext() ) {
|
||||
final Property cidSubProperty = cidPropertyItr.next();
|
||||
|
||||
final SingularPersistentAttribute<?, Object> cidSubAttr = attributeFactory.buildIdAttribute(
|
||||
identifiableType,
|
||||
cidSubProperty
|
||||
);
|
||||
|
||||
idAttributes.add( cidSubAttr );
|
||||
}
|
||||
|
||||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyNonAggregatedIdAttributes( idAttributes );
|
||||
|
||||
|
||||
// see if it also has an IdClass (identifier-mapper)
|
||||
final Component idClass = persistentClass.getIdentifierMapper();
|
||||
if ( idClass != null ) {
|
||||
// todo (6.0) : handle `@IdClass`
|
||||
throw new NotYetImplementedFor6Exception( "Support for @IdClass not yet implemented" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -419,7 +427,7 @@ public class MetadataContext {
|
|||
propertyIterator
|
||||
);
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer) jpaMappingType ).getInFlightAccess().applyIdClassAttributes( attributes );
|
||||
( ( AttributeContainer<X>) jpaMappingType ).getInFlightAccess().applyIdClassAttributes( attributes );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,7 +435,7 @@ public class MetadataContext {
|
|||
final Property declaredVersion = persistentClass.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer) jpaEntityType ).getInFlightAccess().applyVersionAttribute(
|
||||
( ( AttributeContainer<X>) jpaEntityType ).getInFlightAccess().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion )
|
||||
);
|
||||
}
|
||||
|
@ -437,7 +445,7 @@ public class MetadataContext {
|
|||
final Property declaredVersion = mappingType.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
//noinspection unchecked
|
||||
( ( AttributeContainer) jpaMappingType ).getInFlightAccess().applyVersionAttribute(
|
||||
( ( AttributeContainer<X>) jpaMappingType ).getInFlightAccess().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion )
|
||||
);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public class StandardManagedTypeRepresentationResolver implements ManagedTypeRep
|
|||
// RepresentationMode representation = bootDescriptor.getExplicitRepresentationMode();
|
||||
RepresentationMode representation = null;
|
||||
if ( representation == null ) {
|
||||
if ( bootDescriptor.getComponentClass() == null ) {
|
||||
if ( bootDescriptor.getComponentClassName() == null ) {
|
||||
representation = RepresentationMode.MAP;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -81,6 +81,36 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
return mappingType;
|
||||
}
|
||||
|
||||
public static EmbeddableMappingType from(
|
||||
Component bootDescriptor,
|
||||
CompositeType compositeType,
|
||||
NavigableRole embeddedRole,
|
||||
Function<EmbeddableMappingType,EmbeddableValuedModelPart> embeddedPartBuilder,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
|
||||
|
||||
final EmbeddableRepresentationStrategy representationStrategy = creationContext.getBootstrapContext()
|
||||
.getRepresentationStrategySelector()
|
||||
.resolveStrategy( bootDescriptor, creationContext );
|
||||
|
||||
final EmbeddableMappingType mappingType = new EmbeddableMappingType(
|
||||
bootDescriptor,
|
||||
representationStrategy,
|
||||
embeddedPartBuilder,
|
||||
creationContext.getSessionFactory()
|
||||
);
|
||||
|
||||
creationProcess.registerInitializationCallback(
|
||||
() -> mappingType.finishInitialization(
|
||||
bootDescriptor,
|
||||
compositeType,
|
||||
creationProcess
|
||||
)
|
||||
);
|
||||
|
||||
return mappingType;
|
||||
}
|
||||
|
||||
private final JavaTypeDescriptor embeddableJtd;
|
||||
private final EmbeddableRepresentationStrategy representationStrategy;
|
||||
|
||||
|
@ -90,6 +120,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
private final Map<String,AttributeMapping> attributeMappings = new LinkedHashMap<>();
|
||||
|
||||
private final EmbeddableValuedModelPart valueMapping;
|
||||
private NavigableRole embeddedRole;
|
||||
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
|
||||
|
@ -139,6 +170,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
bootPropertyDescriptor.getName(),
|
||||
MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
|
@ -194,6 +226,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
else if ( subtype instanceof EntityType ) {
|
||||
final SingularAssociationAttributeMapping singularAssociationAttributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
|
|
|
@ -59,6 +59,7 @@ public class BasicValuedSingularAttributeMapping
|
|||
@SuppressWarnings("WeakerAccess")
|
||||
public BasicValuedSingularAttributeMapping(
|
||||
String attributeName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
FetchStrategy mappedFetchStrategy,
|
||||
|
@ -69,7 +70,7 @@ public class BasicValuedSingularAttributeMapping
|
|||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess) {
|
||||
super( attributeName, stateArrayPosition, attributeMetadataAccess, mappedFetchStrategy, declaringType, propertyAccess );
|
||||
this.navigableRole = declaringType.getNavigableRole().append( attributeName );
|
||||
this.navigableRole = navigableRole;
|
||||
this.tableExpression = tableExpression;
|
||||
this.mappedColumnExpression = mappedColumnExpression;
|
||||
this.valueConverter = valueConverter;
|
||||
|
|
|
@ -12,8 +12,10 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.collection.internal.StandardArraySemantics;
|
||||
|
@ -27,6 +29,7 @@ import org.hibernate.engine.FetchStyle;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadeStyles;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
@ -63,16 +66,20 @@ import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.SQLLoadableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
@ -116,10 +123,10 @@ public class MappingModelCreationHelper {
|
|||
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
||||
(Component) bootProperty.getValue(),
|
||||
cidType,
|
||||
attributeMappingType -> new EmbeddedIdentifierMappingImpl(
|
||||
embeddable -> new EmbeddedIdentifierMappingImpl(
|
||||
entityPersister,
|
||||
attributeName,
|
||||
attributeMappingType,
|
||||
embeddable,
|
||||
attributeMetadataAccess,
|
||||
propertyAccess,
|
||||
rootTableName,
|
||||
|
@ -135,20 +142,119 @@ public class MappingModelCreationHelper {
|
|||
|
||||
public static CompositeIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
EntityPersister entityPersister,
|
||||
List<SingularAttributeMapping> idAttributeMappings,
|
||||
String rootTableName,
|
||||
String[] rootTableKeyColumnNames,
|
||||
CompositeType cidType,
|
||||
PersistentClass bootEntityDescriptor,
|
||||
BiConsumer<String,SingularAttributeMapping> idSubAttributeConsumer,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final Component bootCompositeDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||
|
||||
return new NonAggregatedIdentifierMappingImpl(
|
||||
entityPersister,
|
||||
idAttributeMappings,
|
||||
final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
|
||||
null,
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME
|
||||
);
|
||||
|
||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess(
|
||||
propertyAccess
|
||||
);
|
||||
|
||||
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
||||
bootCompositeDescriptor,
|
||||
cidType,
|
||||
attributeMappingType -> {
|
||||
final Component bootIdDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||
|
||||
final List<SingularAttributeMapping> idAttributeMappings = new ArrayList<>( bootIdDescriptor.getPropertySpan() );
|
||||
|
||||
//noinspection unchecked
|
||||
final Iterator<Property> bootIdSubPropertyItr = bootIdDescriptor.getPropertyIterator();
|
||||
int columnsConsumedSoFar = 0;
|
||||
|
||||
while ( bootIdSubPropertyItr.hasNext() ) {
|
||||
final Property bootIdSubProperty = bootIdSubPropertyItr.next();
|
||||
final Type idSubPropertyType = bootIdSubProperty.getType();
|
||||
|
||||
if ( idSubPropertyType instanceof AnyType ) {
|
||||
throw new HibernateException(
|
||||
"AnyType property `" + bootEntityDescriptor.getEntityName() + "#" + bootIdSubProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
if ( idSubPropertyType instanceof CollectionType ) {
|
||||
throw new HibernateException(
|
||||
"Plural property `" + bootEntityDescriptor.getEntityName() + "#" + bootIdSubProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
final SingularAttributeMapping idSubAttribute;
|
||||
|
||||
if ( idSubPropertyType instanceof BasicType ) {
|
||||
//noinspection rawtypes
|
||||
idSubAttribute = buildBasicAttributeMapping(
|
||||
bootIdSubProperty.getName(),
|
||||
entityPersister.getNavigableRole().append( bootIdSubProperty.getName() ),
|
||||
idAttributeMappings.size(),
|
||||
bootIdSubProperty,
|
||||
attributeMappingType,
|
||||
(BasicType) idSubPropertyType,
|
||||
rootTableName,
|
||||
rootTableKeyColumnNames[columnsConsumedSoFar],
|
||||
entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ),
|
||||
CascadeStyles.ALL,
|
||||
creationProcess
|
||||
);
|
||||
columnsConsumedSoFar++;
|
||||
}
|
||||
else if ( idSubPropertyType instanceof CompositeType ) {
|
||||
// nested composite
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
else if ( idSubPropertyType instanceof EntityType ) {
|
||||
// key-many-to-one
|
||||
final EntityType keyManyToOnePropertyType = (EntityType) idSubPropertyType;
|
||||
|
||||
idSubAttribute = buildSingularAssociationAttributeMapping(
|
||||
bootIdSubProperty.getName(),
|
||||
entityPersister.getNavigableRole().append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
|
||||
idAttributeMappings.size(),
|
||||
bootIdSubProperty,
|
||||
attributeMappingType,
|
||||
keyManyToOnePropertyType,
|
||||
entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ),
|
||||
CascadeStyles.ALL,
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnsConsumedSoFar += keyManyToOnePropertyType.getColumnSpan( sessionFactory );
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
idAttributeMappings.add( idSubAttribute );
|
||||
idSubAttributeConsumer.accept( idSubAttribute.getAttributeName(), idSubAttribute );
|
||||
}
|
||||
|
||||
return new NonAggregatedIdentifierMappingImpl(
|
||||
attributeMappingType,
|
||||
entityPersister,
|
||||
idAttributeMappings,
|
||||
attributeMetadataAccess,
|
||||
rootTableName,
|
||||
rootTableKeyColumnNames,
|
||||
bootCompositeDescriptor,
|
||||
bootEntityDescriptor.getDeclaredIdentifierMapper(),
|
||||
creationProcess
|
||||
);
|
||||
},
|
||||
creationProcess
|
||||
);
|
||||
|
||||
return (CompositeIdentifierMapping) embeddableMappingType.getEmbeddedValueMapping();
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,6 +264,7 @@ public class MappingModelCreationHelper {
|
|||
@SuppressWarnings("rawtypes")
|
||||
public static BasicValuedSingularAttributeMapping buildBasicAttributeMapping(
|
||||
String attrName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
|
@ -240,6 +347,7 @@ public class MappingModelCreationHelper {
|
|||
|
||||
return new BasicValuedSingularAttributeMapping(
|
||||
attrName,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
attributeMetadataAccess,
|
||||
fetchStrategy,
|
||||
|
@ -254,6 +362,7 @@ public class MappingModelCreationHelper {
|
|||
else {
|
||||
return new BasicValuedSingularAttributeMapping(
|
||||
attrName,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
attributeMetadataAccess,
|
||||
fetchStrategy,
|
||||
|
@ -1141,6 +1250,7 @@ public class MappingModelCreationHelper {
|
|||
|
||||
public static SingularAssociationAttributeMapping buildSingularAssociationAttributeMapping(
|
||||
String attrName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
|
@ -1183,6 +1293,7 @@ public class MappingModelCreationHelper {
|
|||
|
||||
final SingularAssociationAttributeMapping attributeMapping = new SingularAssociationAttributeMapping(
|
||||
attrName,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
(ToOne) bootProperty.getValue(),
|
||||
stateArrayContributorMetadataAccess,
|
||||
|
|
|
@ -6,21 +6,44 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -33,23 +56,37 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMapping {
|
||||
public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMapping, EmbeddableValuedFetchable {
|
||||
private final EmbeddableMappingType embeddableDescriptor;
|
||||
private final NavigableRole navigableRole;
|
||||
private final EntityMappingType entityMapping;
|
||||
|
||||
private final List<SingularAttributeMapping> idAttributeMappings;
|
||||
|
||||
private final StateArrayContributorMetadataAccess attributeMetadataAccess;
|
||||
private final String rootTableName;
|
||||
private final List<String> idColumnNames;
|
||||
|
||||
public NonAggregatedIdentifierMappingImpl(
|
||||
EmbeddableMappingType embeddableDescriptor,
|
||||
EntityMappingType entityMapping,
|
||||
List<SingularAttributeMapping> idAttributeMappings,
|
||||
Component bootIdDescriptor,
|
||||
CompositeType cidType,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
String rootTableName,
|
||||
String[] rootTableKeyColumnNames,
|
||||
Component bootCidDescriptor,
|
||||
Component bootIdClassDescriptor,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
// todo (6.0) : handle MapsId and IdClass
|
||||
// todo (6.0) : implement SQL AST apis (DomainResult, e.g.)
|
||||
this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
|
||||
this.embeddableDescriptor = embeddableDescriptor;
|
||||
this.entityMapping = entityMapping;
|
||||
this.idAttributeMappings = idAttributeMappings;
|
||||
this.attributeMetadataAccess = attributeMetadataAccess;
|
||||
this.rootTableName = rootTableName;
|
||||
this.idColumnNames = Arrays.asList( rootTableKeyColumnNames );
|
||||
|
||||
this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,8 +105,8 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getMappedTypeDescriptor() {
|
||||
return entityMapping;
|
||||
public EmbeddableMappingType getMappedTypeDescriptor() {
|
||||
return embeddableDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,8 +140,12 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
// we will need a specialized impl for this
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
return new EmbeddableResultImpl<>(
|
||||
navigablePath,
|
||||
this,
|
||||
resultVariable,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,4 +153,109 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
return entityMapping;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// EmbeddableValuedFetchable
|
||||
|
||||
|
||||
@Override
|
||||
public EmbeddableMappingType getEmbeddableTypeDescriptor() {
|
||||
return getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
return rootTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMappedColumnExpressions() {
|
||||
return idColumnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeMapping getParentInjectionAttributeMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
TableGroup tableGroup,
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroupJoin createTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final CompositeTableGroup compositeTableGroup = new CompositeTableGroup(
|
||||
navigablePath,
|
||||
this,
|
||||
lhs
|
||||
);
|
||||
|
||||
final TableGroupJoin join = new TableGroupJoin( navigablePath, SqlAstJoinType.LEFT, compositeTableGroup, null );
|
||||
lhs.addTableGroupJoin( join );
|
||||
|
||||
return join;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlAliasStem() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||
return getMappedTypeDescriptor().findSubPart( name, treatTargetType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
|
||||
getMappedTypeDescriptor().visitSubParts( consumer, treatTargetType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getMappedFetchStrategy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
NavigablePath fetchablePath,
|
||||
FetchTiming fetchTiming,
|
||||
boolean selected,
|
||||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return new EmbeddableFetchImpl(
|
||||
fetchablePath,
|
||||
this,
|
||||
fetchParent,
|
||||
fetchTiming,
|
||||
selected,
|
||||
attributeMetadataAccess.resolveAttributeMetadata( null ).isNullable(),
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return idAttributeMappings.size();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
|
||||
public SingularAssociationAttributeMapping(
|
||||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
ToOne bootValue,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
|
@ -124,7 +125,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
cardinality = Cardinality.ONE_TO_ONE;
|
||||
}
|
||||
|
||||
this.navigableRole = declaringType.getNavigableRole().appendContainer( name );
|
||||
this.navigableRole = navigableRole;
|
||||
}
|
||||
|
||||
public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) {
|
||||
|
|
|
@ -41,8 +41,10 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
private final boolean hasIdentifierProperty;
|
||||
private final boolean hasIdClass;
|
||||
|
||||
private SingularPersistentAttribute<J,?> id;
|
||||
private Set<SingularPersistentAttribute<? super J,?>> idClassAttributes;
|
||||
private Set<SingularPersistentAttribute<? super J,?>> nonAggregatedIdAttributes;
|
||||
|
||||
private SqmPathSource identifierDescriptor;
|
||||
|
||||
|
||||
|
@ -221,8 +223,8 @@ public abstract class AbstractIdentifiableType<J>
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void visitIdClassAttributes(Consumer<SingularPersistentAttribute<? super J, ?>> attributeConsumer) {
|
||||
if ( idClassAttributes != null ) {
|
||||
idClassAttributes.forEach( attributeConsumer );
|
||||
if ( nonAggregatedIdAttributes != null ) {
|
||||
nonAggregatedIdAttributes.forEach( attributeConsumer );
|
||||
}
|
||||
else if ( getSuperType() != null ) {
|
||||
getSuperType().visitIdClassAttributes( (Consumer) attributeConsumer );
|
||||
|
@ -305,6 +307,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
return versionAttribute;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private class InFlightAccessImpl extends AbstractManagedType.InFlightAccessImpl {
|
||||
private final AbstractManagedType.InFlightAccess managedTypeAccess;
|
||||
|
||||
|
@ -313,23 +316,28 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void applyIdAttribute(SingularPersistentAttribute idAttribute) {
|
||||
AbstractIdentifiableType.this.id = idAttribute;
|
||||
managedTypeAccess.addAttribute( idAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void applyIdClassAttributes(Set idClassAttributes) {
|
||||
for ( SingularAttribute idClassAttribute : ( (Set<SingularPersistentAttribute>) idClassAttributes ) ) {
|
||||
if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
SingularPersistentAttribute<J,?> declaredAttribute = (SingularPersistentAttribute) idClassAttribute;
|
||||
addAttribute( declaredAttribute );
|
||||
public void applyNonAggregatedIdAttributes(Set idAttributes) {
|
||||
if ( AbstractIdentifiableType.this.id != null ) {
|
||||
throw new IllegalArgumentException( "`AbstractIdentifiableType#id` already set on call to `#applyNonAggregatedIdAttribute`" );
|
||||
}
|
||||
|
||||
if ( nonAggregatedIdAttributes != null ) {
|
||||
throw new IllegalStateException( "Non-aggregated id attributes were already set" );
|
||||
}
|
||||
|
||||
for ( SingularPersistentAttribute idAttribute : (Set<SingularPersistentAttribute>) idAttributes ) {
|
||||
if ( AbstractIdentifiableType.this == idAttribute.getDeclaringType() ) {
|
||||
addAttribute( idAttribute );
|
||||
}
|
||||
}
|
||||
AbstractIdentifiableType.this.idClassAttributes = idClassAttributes;
|
||||
|
||||
AbstractIdentifiableType.this.nonAggregatedIdAttributes = (Set) idAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -383,7 +391,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
);
|
||||
}
|
||||
}
|
||||
else if ( idClassAttributes != null && ! idClassAttributes.isEmpty() ) {
|
||||
else if ( nonAggregatedIdAttributes != null && ! nonAggregatedIdAttributes.isEmpty() ) {
|
||||
// non-aggregate composite id
|
||||
return new NonAggregatedCompositeSqmPathSource(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
|
@ -23,12 +24,27 @@ public interface AttributeContainer<J> {
|
|||
interface InFlightAccess<J> {
|
||||
void addAttribute(PersistentAttribute<J,?> attribute);
|
||||
|
||||
/**
|
||||
* Callback used when we have a singular id attribute of some form - either a simple id
|
||||
* or an aggregated composite id ({@link javax.persistence.EmbeddedId
|
||||
*/
|
||||
default void applyIdAttribute(SingularPersistentAttribute<J, ?> idAttribute) {
|
||||
throw new UnsupportedOperationException(
|
||||
"AttributeContainer [" + getClass().getName() + "] does not support identifiers"
|
||||
);
|
||||
}
|
||||
|
||||
default void applyNonAggregatedIdAttributes(Set<SingularPersistentAttribute<? super J, ?>> idAttributes) {
|
||||
throw new UnsupportedOperationException(
|
||||
"AttributeContainer [" + getClass().getName() + "] does not support identifiers"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* todo (6.0) : we still need to implement this properly and the contract may change
|
||||
* - specifically I am not certain we will be able to re-use `SingularPersistentAttribute`
|
||||
* because of its dependence on declaring-type, etc that we may not be able to do
|
||||
*/
|
||||
default void applyIdClassAttributes(Set<SingularPersistentAttribute<? super J, ?>> idClassAttributes) {
|
||||
throw new UnsupportedOperationException(
|
||||
"AttributeContainer [" + getClass().getName() + "] does not support identifiers"
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
|||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.DynamicModelJtd;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -515,12 +516,14 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
|||
PersistentClass persistentClass,
|
||||
MetadataContext context,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final Class javaType = persistentClass.getMappedClass();
|
||||
context.pushEntityWorkedOn( persistentClass );
|
||||
|
||||
final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass();
|
||||
|
||||
IdentifiableDomainType<?> superType = superMappedSuperclass == null
|
||||
? null
|
||||
: locateOrBuildMappedSuperclassType( superMappedSuperclass, context, typeConfiguration );
|
||||
|
||||
//no mappedSuperclass, check for a super entity
|
||||
if ( superType == null ) {
|
||||
final PersistentClass superPersistentClass = persistentClass.getSuperclass();
|
||||
|
@ -529,17 +532,28 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
|||
: locateOrBuildEntityType( superPersistentClass, context, typeConfiguration );
|
||||
}
|
||||
|
||||
final JavaTypeDescriptor javaTypeDescriptor = context.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( javaType );
|
||||
final EntityTypeImpl entityType = new EntityTypeImpl(
|
||||
final Class<?> javaType = persistentClass.getMappedClass();
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor;
|
||||
if ( javaType == null || Map.class.isAssignableFrom( javaType ) ) {
|
||||
// dynamic map
|
||||
javaTypeDescriptor = new DynamicModelJtd();
|
||||
}
|
||||
else {
|
||||
javaTypeDescriptor = context.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( javaType );
|
||||
}
|
||||
|
||||
final EntityTypeImpl<?> entityType = new EntityTypeImpl(
|
||||
javaTypeDescriptor,
|
||||
superType,
|
||||
persistentClass,
|
||||
this
|
||||
);
|
||||
|
||||
context.registerEntityType( persistentClass, entityType );
|
||||
context.popEntityWorkedOn( persistentClass );
|
||||
|
||||
return entityType;
|
||||
}
|
||||
|
||||
|
|
|
@ -6039,83 +6039,17 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
private EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapping(
|
||||
MappingModelCreationProcess creationProcess,
|
||||
PersistentClass bootEntityDescriptor, CompositeType cidType) {
|
||||
// process all of the defined "id attributes" because they are declared on the entity
|
||||
final Component bootIdDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||
final List<SingularAttributeMapping> idAttributeMappings = new ArrayList<>( bootIdDescriptor.getPropertySpan() );
|
||||
int columnsConsumedSoFar = 0;
|
||||
|
||||
if ( attributeMappings == null ) {
|
||||
attributeMappings = new ArrayList<>(
|
||||
bootEntityDescriptor.getPropertyClosureSpan() + bootIdDescriptor.getPropertySpan()
|
||||
);
|
||||
|
||||
final Iterator bootPropertyIterator = bootIdDescriptor.getPropertyIterator();
|
||||
while ( bootPropertyIterator.hasNext() ) {
|
||||
final Property bootIdProperty = (Property) bootPropertyIterator.next();
|
||||
final Type idPropertyType = bootIdProperty.getType();
|
||||
|
||||
if ( idPropertyType instanceof AnyType ) {
|
||||
throw new HibernateException(
|
||||
"AnyType property `" + getEntityName() + "#" + bootIdProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
if ( idPropertyType instanceof CollectionType ) {
|
||||
throw new HibernateException(
|
||||
"Plural property `" + getEntityName() + "#" + bootIdProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
final SingularAttributeMapping idAttributeMapping;
|
||||
|
||||
if ( idPropertyType instanceof BasicType ) {
|
||||
idAttributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootIdProperty.getName(),
|
||||
attributeMappings.size(),
|
||||
bootIdProperty,
|
||||
this,
|
||||
(BasicType) idPropertyType,
|
||||
getRootTableName(),
|
||||
rootTableKeyColumnNames[columnsConsumedSoFar],
|
||||
getRepresentationStrategy().resolvePropertyAccess( bootIdProperty ),
|
||||
CascadeStyles.ALL,
|
||||
creationProcess
|
||||
);
|
||||
columnsConsumedSoFar++;
|
||||
}
|
||||
else {
|
||||
// final String[] unconsumedColumnNames = Arrays.copyOfRange(
|
||||
// rootTableKeyColumnNames,
|
||||
// columnsConsumedSoFar,
|
||||
// rootTableKeyColumnNames.length
|
||||
// );
|
||||
|
||||
if ( idPropertyType instanceof CompositeType ) {
|
||||
// nested composite
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
else if ( idPropertyType instanceof EntityType ) {
|
||||
// key-many-to-one
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
idAttributeMappings.add( idAttributeMapping );
|
||||
}
|
||||
}
|
||||
attributeMappings.addAll( idAttributeMappings );
|
||||
PersistentClass bootEntityDescriptor,
|
||||
CompositeType cidType) {
|
||||
assert declaredAttributeMappings != null;
|
||||
|
||||
return MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
this,
|
||||
idAttributeMappings,
|
||||
getRootTableName(),
|
||||
getRootTableKeyColumnNames(),
|
||||
cidType,
|
||||
bootEntityDescriptor,
|
||||
declaredAttributeMappings::put,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
@ -6167,6 +6101,7 @@ public abstract class AbstractEntityPersister
|
|||
if ( propertyIndex == getVersionProperty() ) {
|
||||
return MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
attrName,
|
||||
getNavigableRole().append( bootProperty.getName() ),
|
||||
stateArrayPosition,
|
||||
bootProperty,
|
||||
this,
|
||||
|
@ -6182,6 +6117,7 @@ public abstract class AbstractEntityPersister
|
|||
if ( attrType instanceof BasicType ) {
|
||||
return MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
attrName,
|
||||
getNavigableRole().append( bootProperty.getName() ),
|
||||
stateArrayPosition,
|
||||
bootProperty,
|
||||
this,
|
||||
|
@ -6222,6 +6158,7 @@ public abstract class AbstractEntityPersister
|
|||
else if ( attrType instanceof EntityType ) {
|
||||
SingularAssociationAttributeMapping attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||
attrName,
|
||||
getNavigableRole().append( attrName ),
|
||||
stateArrayPosition,
|
||||
bootProperty,
|
||||
this,
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.hql.internal;
|
|||
import org.hibernate.QueryException;
|
||||
import org.hibernate.grammars.hql.HqlLexer;
|
||||
import org.hibernate.grammars.hql.HqlParser;
|
||||
import org.hibernate.query.hql.HqlLogger;
|
||||
import org.hibernate.query.sqm.InterpretationException;
|
||||
import org.hibernate.query.hql.HqlTranslator;
|
||||
import org.hibernate.query.sqm.internal.SqmTreePrinter;
|
||||
|
@ -31,6 +32,7 @@ public class StandardHqlTranslator implements HqlTranslator {
|
|||
private final SqmCreationContext sqmCreationContext;
|
||||
private final SqmCreationOptions sqmCreationOptions;
|
||||
|
||||
|
||||
public StandardHqlTranslator(
|
||||
SqmCreationContext sqmCreationContext,
|
||||
SqmCreationOptions sqmCreationOptions) {
|
||||
|
@ -40,6 +42,8 @@ public class StandardHqlTranslator implements HqlTranslator {
|
|||
|
||||
@Override
|
||||
public SqmStatement translate(String query) {
|
||||
HqlLogger.QUERY_LOGGER.debugf( "HQL : " + query );
|
||||
|
||||
final HqlParser.StatementContext hqlParseTree = parseHql( query );
|
||||
|
||||
// then we perform semantic analysis and build the semantic representation...
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.type.descriptor.java.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
|
||||
/**
|
||||
* JavaTypeDescriptor for dynamic models
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicModelJtd implements JavaTypeDescriptor<Map<?,?>> {
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<?,?> fromString(String string) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X unwrap(Map<?,?> value, Class<X> type, WrapperOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Map<?,?> wrap(X value, WrapperOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Map<?,?>> getJavaTypeClass() {
|
||||
//noinspection unchecked,rawtypes
|
||||
return (Class) Map.class;
|
||||
}
|
||||
}
|
|
@ -7,16 +7,12 @@
|
|||
package org.hibernate.type.descriptor.java.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.SerializableTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.type.spi.TypeConfigurationAware;
|
||||
|
||||
|
@ -155,34 +151,8 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
|
|||
);
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor<?> resolveDynamicDescriptor(String typeName) {
|
||||
return new DynamicJtd();
|
||||
public JavaTypeDescriptor<?> resolveDynamicEntityDescriptor(String typeName) {
|
||||
return new DynamicModelJtd();
|
||||
}
|
||||
|
||||
private static class DynamicJtd implements JavaTypeDescriptor<Map> {
|
||||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map fromString(String string) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X unwrap(Map value, Class<X> type, WrapperOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Map wrap(X value, WrapperOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Map> getJavaTypeClass() {
|
||||
return Map.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.cid.nonaggregated.dynamic;
|
||||
|
||||
/**
|
||||
* Entity used as target for a key-many-to-one
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ChangeGroup {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* For persistence
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private ChangeGroup() {
|
||||
}
|
||||
|
||||
public ChangeGroup(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
-->
|
||||
<hibernate-mapping auto-import="false" xmlns="http://www.hibernate.org/xsd/orm/hbm">
|
||||
<class table="hbm_dynamic_cid_basic" entity-name="DynamicCompositeIdBasic" abstract="false">
|
||||
<composite-id name="id">
|
||||
<key-property name="key1" type="integer"/>
|
||||
<key-property name="key2" type="integer"/>
|
||||
</composite-id>
|
||||
|
||||
<property insert="true" name="attr1" type="string"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.cid.nonaggregated.dynamic;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry(
|
||||
settings = @ServiceRegistry.Setting( name = AvailableSettings.HBM2DDL_AUTO, value = "create-drop" )
|
||||
)
|
||||
public class DynamicCompositeIdBasicTests {
|
||||
@Test
|
||||
public void testBinding(ServiceRegistryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( scope.getRegistry() )
|
||||
.addResource( "org/hibernate/orm/test/bootstrap/binding/hbm/cid/nonaggregated/dynamic/DynamicCompositeIdBasic.hbm.xml" )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
|
||||
try {
|
||||
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.findEntityDescriptor( "DynamicCompositeIdBasic" );
|
||||
|
||||
assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 3 ) );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
assertThat( identifierMapping, instanceOf( NonAggregatedIdentifierMappingImpl.class ) );
|
||||
final NonAggregatedIdentifierMappingImpl cid = (NonAggregatedIdentifierMappingImpl) identifierMapping;
|
||||
assertThat( cid.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings(), is( 2 ) );
|
||||
|
||||
final AttributeMapping key1 = cid.getEmbeddableTypeDescriptor().findAttributeMapping( "key1" );
|
||||
assertThat( key1, notNullValue() );
|
||||
|
||||
final AttributeMapping key2 = cid.getEmbeddableTypeDescriptor().findAttributeMapping( "key2" );
|
||||
assertThat( key2, notNullValue() );
|
||||
|
||||
final AttributeMapping attr1 = entityDescriptor.findAttributeMapping( "attr1" );
|
||||
assertThat( attr1, notNullValue() );
|
||||
|
||||
sessionFactory.inTransaction(
|
||||
session -> session.createQuery( "from DynamicCompositeIdBasic e where e.key1 = 1" ).list()
|
||||
);
|
||||
}
|
||||
finally {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
-->
|
||||
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/orm/hbm" package="org.hibernate.orm.test.bootstrap.binding.hbm.cid.nonaggregated.dynamic">
|
||||
<class name="ChangeGroup">
|
||||
<id name="id"/>
|
||||
<property name="name" />
|
||||
</class>
|
||||
|
||||
<class entity-name="DynamicCompositeIdManyToOne" table="hbm_dynamic_cid_m2o" >
|
||||
<composite-id name="id">
|
||||
<key-property name="key1" type="integer"/>
|
||||
<key-many-to-one name="key2" class="ChangeGroup"/>
|
||||
</composite-id>
|
||||
|
||||
<property name="attr1" type="string"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.cid.nonaggregated.dynamic;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl;
|
||||
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
|
||||
|
||||
/**
|
||||
* Note that this test uses a composite-id with key-many-to-one as part of a
|
||||
* dynamic model, which is the main construct needed by hibernate-envers
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry(
|
||||
settings = @ServiceRegistry.Setting( name = AvailableSettings.HBM2DDL_AUTO, value = "create-drop" )
|
||||
)
|
||||
public class DynamicCompositeIdManyToOneTests {
|
||||
@Test
|
||||
public void testBinding(ServiceRegistryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( scope.getRegistry() )
|
||||
.addResource( "org/hibernate/orm/test/bootstrap/binding/hbm/cid/nonaggregated/dynamic/DynamicCompositeIdManyToOne.hbm.xml" )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
|
||||
try {
|
||||
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.findEntityDescriptor( "DynamicCompositeIdManyToOne" );
|
||||
|
||||
assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 3 ) );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
assertThat( identifierMapping, instanceOf( NonAggregatedIdentifierMappingImpl.class ) );
|
||||
final NonAggregatedIdentifierMappingImpl cid = (NonAggregatedIdentifierMappingImpl) identifierMapping;
|
||||
assertThat( cid.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings(), is( 2 ) );
|
||||
|
||||
final AttributeMapping key1 = cid.getEmbeddableTypeDescriptor().findAttributeMapping( "key1" );
|
||||
assertThat( key1, notNullValue() );
|
||||
assertThat( key1, instanceOf( BasicValuedSingularAttributeMapping.class ) );
|
||||
|
||||
final AttributeMapping key2 = cid.getEmbeddableTypeDescriptor().findAttributeMapping( "key2" );
|
||||
assertThat( key2, notNullValue() );
|
||||
assertThat( key2, instanceOf( SingularAssociationAttributeMapping.class ) );
|
||||
|
||||
final AttributeMapping attr1 = entityDescriptor.findAttributeMapping( "attr1" );
|
||||
assertThat( attr1, notNullValue() );
|
||||
assertThat( attr1, instanceOf( BasicValuedSingularAttributeMapping.class ) );
|
||||
|
||||
assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 3 ) );
|
||||
|
||||
inTransaction(
|
||||
sessionFactory,
|
||||
session -> {
|
||||
session.createQuery( "select e__ from DynamicCompositeIdManyToOne e__" ).list();
|
||||
session.createQuery( "select e__ from DynamicCompositeIdManyToOne e__ where e__.key1 = 1" ).list();
|
||||
session.createQuery( "select e__ from DynamicCompositeIdManyToOne e__ where e__.key2.name = 'abc'" ).list();
|
||||
}
|
||||
);
|
||||
}
|
||||
finally {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
-->
|
||||
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/orm/hbm" >
|
||||
<class entity-name="SimpleDynamicEntity" table="hbm_simple_entity_dynamic" >
|
||||
<id name="id" type="integer"/>
|
||||
<property name="name" type="string"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.simple.dynamic;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry(
|
||||
settings = @ServiceRegistry.Setting( name = AvailableSettings.HBM2DDL_AUTO, value = "create-drop" )
|
||||
)
|
||||
public class SimpleDynamicHbmTests {
|
||||
@Test
|
||||
public void testBinding(ServiceRegistryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( scope.getRegistry() )
|
||||
.addResource( "org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicEntity.hbm.xml" )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
|
||||
try {
|
||||
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.findEntityDescriptor( "SimpleDynamicEntity" );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
assertThat( identifierMapping, instanceOf( BasicEntityIdentifierMapping.class ) );
|
||||
final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping;
|
||||
assertThat( bid.getFetchableName(), is( "id" ) );
|
||||
assertThat( bid.getPartName(), is( EntityIdentifierMapping.ROLE_LOCAL_NAME ) );
|
||||
|
||||
assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 1 ) );
|
||||
assertThat( entityDescriptor.getNumberOfDeclaredAttributeMappings(), is( 1 ) );
|
||||
final AttributeMapping nameAttr = entityDescriptor.findAttributeMapping( "name" );
|
||||
assertThat( nameAttr, notNullValue() );
|
||||
|
||||
sessionFactory.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "from SimpleDynamicEntity" ).list();
|
||||
session.createQuery( "select e from SimpleDynamicEntity e" ).list();
|
||||
session.createQuery( "select e from SimpleDynamicEntity e.name = 'abc'" ).list();
|
||||
}
|
||||
);
|
||||
}
|
||||
finally {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
-->
|
||||
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/orm/hbm" package="org.hibernate.orm.test.bootstrap.binding.hbm.simple.pojo">
|
||||
<class name="SimpleEntity" table="hbm_simple_entity_pojo" >
|
||||
<id name="id"/>
|
||||
<property name="name"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.simple.pojo;
|
||||
|
||||
/**
|
||||
* Entity for testing simply HBM mapping
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleEntity {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* For Hibernate
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private SimpleEntity() {
|
||||
}
|
||||
|
||||
public SimpleEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.binding.hbm.simple.pojo;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry
|
||||
public class SimpleHbmTests {
|
||||
@Test
|
||||
public void testBinding(ServiceRegistryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( scope.getRegistry() )
|
||||
.addResource( "org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleEntity.hbm.xml" )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
|
||||
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.findEntityDescriptor( SimpleEntity.class );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
assertThat( identifierMapping, instanceOf( BasicEntityIdentifierMapping.class ) );
|
||||
final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping;
|
||||
assertThat( bid.getFetchableName(), is( "id" ) );
|
||||
assertThat( bid.getPartName(), is( EntityIdentifierMapping.ROLE_LOCAL_NAME ) );
|
||||
|
||||
assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 1 ) );
|
||||
assertThat( entityDescriptor.getNumberOfDeclaredAttributeMappings(), is( 1 ) );
|
||||
final AttributeMapping nameAttr = entityDescriptor.findAttributeMapping( "name" );
|
||||
assertThat( nameAttr, notNullValue() );
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ public class SimpleOpsTest extends AbstractOperationTestCase {
|
|||
}
|
||||
|
||||
public String[] getMappings() {
|
||||
return new String[] { "ops/SimpleEntity.hbm.xml" };
|
||||
return new String[] { "ops/SimpleDynamicEntity.hbm.xml" };
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.envers.boot;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.LogMessage;
|
||||
import org.jboss.logging.annotations.Message;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.INFO;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
@ValidIdRange( min = 90005601, max = 90005700 )
|
||||
public interface EnversBootLogger extends BasicLogger {
|
||||
String LOGGER_NAME = "org.hibernate.envers.boot";
|
||||
|
||||
EnversBootLogger BOOT_LOGGER = Logger.getMessageLogger(
|
||||
EnversBootLogger.class,
|
||||
LOGGER_NAME
|
||||
);
|
||||
|
||||
boolean TRACE_ENABLED = BOOT_LOGGER.isTraceEnabled();
|
||||
boolean DEBUG_ENABLED = BOOT_LOGGER.isDebugEnabled();
|
||||
|
||||
static String subLoggerName(String subName) {
|
||||
return LOGGER_NAME + '.' + subName;
|
||||
}
|
||||
|
||||
static Logger subLogger(String subName) {
|
||||
return Logger.getLogger( subLoggerName( subName ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log about usage of deprecated Scanner setting
|
||||
*/
|
||||
@LogMessage( level = INFO )
|
||||
@Message(
|
||||
value = "Envers-generated HBM mapping...%n%s",
|
||||
id = 90000001
|
||||
)
|
||||
void jaxbContribution(String hbm);
|
||||
}
|
|
@ -28,6 +28,7 @@ import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
|
|||
import org.hibernate.boot.spi.AdditionalJaxbMappingProducer;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.envers.boot.EnversBootLogger;
|
||||
import org.hibernate.envers.configuration.internal.MappingCollector;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
|
@ -63,21 +64,12 @@ public class AdditionalJaxbMappingProducerImpl implements AdditionalJaxbMappingP
|
|||
|
||||
// atm we do not have distinct origin info for envers
|
||||
final Origin origin = new Origin( SourceType.OTHER, "envers" );
|
||||
// final DOMWriter writer = new DOMWriter();
|
||||
|
||||
final MappingCollector mappingCollector = new MappingCollector() {
|
||||
@Override
|
||||
public void addDocument(Document document) throws DocumentException {
|
||||
dump( document );
|
||||
logXml( document );
|
||||
|
||||
// while the commented-out code here is more efficient (well, understanding that
|
||||
// this whole process is un-efficient) it leads to un-decipherable messages when
|
||||
// we get mapping mapping errors from envers output.
|
||||
// final DOMSource domSource = new DOMSource( writer.write( document ) );
|
||||
// domSource.setSystemId( "envers" );
|
||||
// final Binding jaxbBinding = mappingBinder.bind( domSource, origin );
|
||||
|
||||
// this form at least allows us to get better error messages
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
final Writer w = new BufferedWriter( new OutputStreamWriter( baos, "UTF-8" ) );
|
||||
|
@ -89,11 +81,11 @@ public class AdditionalJaxbMappingProducerImpl implements AdditionalJaxbMappingP
|
|||
throw new HibernateException( "Unable to bind Envers-generated XML", e );
|
||||
}
|
||||
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
|
||||
BufferedInputStream bis = new BufferedInputStream( bais );
|
||||
final Binding jaxbBinding = mappingBinder.bind( bis, origin );
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( baos.toByteArray() );
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream( byteArrayInputStream );
|
||||
final Binding<JaxbHbmHibernateMapping> jaxbBinding = mappingBinder.bind( bufferedInputStream, origin );
|
||||
|
||||
final JaxbHbmHibernateMapping jaxbRoot = (JaxbHbmHibernateMapping) jaxbBinding.getRoot();
|
||||
final JaxbHbmHibernateMapping jaxbRoot = jaxbBinding.getRoot();
|
||||
additionalMappingDocuments.add( new MappingDocument( jaxbRoot, origin, buildingContext ) );
|
||||
}
|
||||
};
|
||||
|
@ -103,13 +95,13 @@ public class AdditionalJaxbMappingProducerImpl implements AdditionalJaxbMappingP
|
|||
return additionalMappingDocuments;
|
||||
}
|
||||
|
||||
private static void dump(Document document) {
|
||||
if ( !log.isTraceEnabled() ) {
|
||||
private static void logXml(Document document) {
|
||||
if ( ! EnversBootLogger.DEBUG_ENABLED ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final Writer w = new PrintWriter( baos );
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
final Writer w = new PrintWriter( outputStream );
|
||||
|
||||
try {
|
||||
final XMLWriter xw = new XMLWriter( w, new OutputFormat( " ", true ) );
|
||||
|
@ -120,7 +112,9 @@ public class AdditionalJaxbMappingProducerImpl implements AdditionalJaxbMappingP
|
|||
throw new RuntimeException( "Error dumping enhanced class", e1 );
|
||||
}
|
||||
|
||||
log.tracef( "Envers-generate entity mapping -----------------------------\n%s", baos.toString() );
|
||||
EnversBootLogger.BOOT_LOGGER.jaxbContribution( outputStream.toString() );
|
||||
|
||||
log.tracef( "Envers-generate entity mapping -----------------------------\n%s", outputStream.toString() );
|
||||
log.trace( "------------------------------------------------------------" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,13 @@ log4j.logger.org.hibernate.tool.hbm2ddl=debug
|
|||
log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=trace
|
||||
log4j.logger.org.hibernate.type.descriptor.sql.BasicExtractor=trace
|
||||
|
||||
log4j.logger.org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl=trace
|
||||
log4j.logger.org.hibernate.envers.jaxb=debug
|
||||
|
||||
log4j.logger.org.hibernate.query=debug
|
||||
log4j.logger.org.hibernate.orm.query=debug
|
||||
|
||||
log4j.logger.org.hibernate.sql.ast=debug
|
||||
log4j.logger.org.hibernate.orm.sql.ast=debug
|
||||
|
||||
log4j.logger.org.hibernate.sql.exec=debug
|
||||
log4j.logger.org.hibernate.orm.sql.exec=debug
|
|
@ -9,6 +9,8 @@ package org.hibernate.testing.boot;
|
|||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.boot.CacheRegionDefinition;
|
||||
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
|
||||
|
@ -141,13 +143,13 @@ public class BootstrapContextImpl implements BootstrapContext {
|
|||
return delegate.getCacheRegionDefinitions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
delegate.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedTypeRepresentationResolver getRepresentationStrategySelector() {
|
||||
return StandardManagedTypeRepresentationResolver.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
delegate.release();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue