slightly sanitize API of mapping package
This commit is contained in:
parent
0359e01c77
commit
12682c0abd
|
@ -1015,7 +1015,7 @@ public class ModelBinder {
|
|||
versionValue.setNullValue( "undefined" );
|
||||
}
|
||||
if ( versionAttributeSource.getSource().equals("db") ) {
|
||||
property.setValueGenerationStrategy(
|
||||
property.setValueGeneratorCreator(
|
||||
context -> new SourceGeneration( DB_SOURCE, property.getType().getReturnedClass() ) );
|
||||
}
|
||||
|
||||
|
@ -2548,7 +2548,7 @@ public class ModelBinder {
|
|||
);
|
||||
}
|
||||
if ( generationTiming.isNotNever() ) {
|
||||
property.setValueGenerationStrategy( context -> new GeneratedValueGeneration( generationTiming ) );
|
||||
property.setValueGeneratorCreator(context -> new GeneratedValueGeneration( generationTiming ) );
|
||||
|
||||
// generated properties can *never* be insertable...
|
||||
if ( property.isInsertable() && generationTiming.includesInsert() ) {
|
||||
|
|
|
@ -381,7 +381,7 @@ public class BinderHelper {
|
|||
clone.setInsertable( false );
|
||||
clone.setUpdateable( false );
|
||||
clone.setNaturalIdentifier( false );
|
||||
clone.setValueGenerationStrategy( property.getValueGenerationStrategy() );
|
||||
clone.setValueGeneratorCreator( property.getValueGeneratorCreator() );
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
|
|||
import org.hibernate.mapping.Array;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.SemanticsResolver;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.usertype.UserCollectionType;
|
||||
|
||||
|
|
|
@ -530,7 +530,7 @@ public class MapBinder extends CollectionBinder {
|
|||
for ( Property property : component.getProperties() ) {
|
||||
final Property newProperty = new Property();
|
||||
newProperty.setCascade( property.getCascade() );
|
||||
newProperty.setValueGenerationStrategy( property.getValueGenerationStrategy() );
|
||||
newProperty.setValueGeneratorCreator( property.getValueGeneratorCreator() );
|
||||
newProperty.setInsertable( false );
|
||||
newProperty.setUpdateable( false );
|
||||
newProperty.setMetaAttributes( property.getMetaAttributes() );
|
||||
|
|
|
@ -365,7 +365,7 @@ public class PropertyBinder {
|
|||
if ( this.property != null ) {
|
||||
if ( entityBinder != null ) {
|
||||
handleNaturalId( property );
|
||||
property.setValueGenerationStrategy( getValueGenerationFromAnnotations( this.property ) );
|
||||
property.setValueGeneratorCreator( getValueGenerationFromAnnotations( this.property ) );
|
||||
}
|
||||
// HHH-4635 -- needed for dialect-specific property ordering
|
||||
property.setLob( this.property.isAnnotationPresent( Lob.class ) );
|
||||
|
|
|
@ -436,17 +436,11 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
RootClass rootClass) throws MappingException {
|
||||
final boolean hasCustomGenerator = ! DEFAULT_ID_GEN_STRATEGY.equals( getIdentifierGeneratorStrategy() );
|
||||
if ( hasCustomGenerator ) {
|
||||
return super.createGenerator(
|
||||
identifierGeneratorFactory,
|
||||
dialect,
|
||||
rootClass
|
||||
);
|
||||
return super.createGenerator( identifierGeneratorFactory, dialect, rootClass );
|
||||
}
|
||||
|
||||
final Class<?> entityClass = rootClass.getMappedClass();
|
||||
final Class<?> attributeDeclarer; // what class is the declarer of the composite pk attributes
|
||||
CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator;
|
||||
|
||||
// IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the
|
||||
// various scenarios for which we need to account here
|
||||
if ( rootClass.getIdentifierMapper() != null ) {
|
||||
|
@ -458,11 +452,12 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
attributeDeclarer = resolveComponentClass();
|
||||
}
|
||||
else {
|
||||
// we have the "straight up" embedded (again the hibernate term) component identifier
|
||||
// we have the "straight up" embedded (again the Hibernate term) component identifier
|
||||
attributeDeclarer = entityClass;
|
||||
}
|
||||
|
||||
locator = new StandardGenerationContextLocator( rootClass.getEntityName() );
|
||||
final CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator =
|
||||
new StandardGenerationContextLocator( rootClass.getEntityName() );
|
||||
final CompositeNestedGeneratedValueGenerator generator = new CompositeNestedGeneratedValueGenerator( locator );
|
||||
|
||||
for ( Property property : getProperties() ) {
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.mapping;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.tuple.Generator;
|
||||
import org.hibernate.tuple.GeneratorCreationContext;
|
||||
|
||||
@Internal
|
||||
@FunctionalInterface
|
||||
public interface GeneratorCreator {
|
||||
Generator createGenerator(GeneratorCreationContext context);
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.mapping;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
|
||||
import org.hibernate.tuple.Generator;
|
||||
|
||||
@Internal
|
||||
@FunctionalInterface
|
||||
public interface IdentifierGeneratorCreator {
|
||||
Generator createGenerator(CustomIdGeneratorCreationContext context);
|
||||
|
|
|
@ -14,19 +14,24 @@ import java.util.Map;
|
|||
import java.util.StringTokenizer;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadeStyles;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.jpa.event.spi.CallbackDefinition;
|
||||
import org.hibernate.metamodel.RepresentationMode;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.PropertyAccessStrategy;
|
||||
import org.hibernate.property.access.spi.PropertyAccessStrategyResolver;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tuple.Generator;
|
||||
import org.hibernate.tuple.GeneratorCreationContext;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -44,7 +49,7 @@ public class Property implements Serializable, MetaAttributable {
|
|||
private boolean insertable = true;
|
||||
private boolean selectable = true;
|
||||
private boolean optimisticLocked = true;
|
||||
private GeneratorCreator generator;
|
||||
private GeneratorCreator generatorCreator;
|
||||
private String propertyAccessorName;
|
||||
private PropertyAccessStrategy propertyAccessStrategy;
|
||||
private boolean lazy;
|
||||
|
@ -215,12 +220,14 @@ public class Property implements Serializable, MetaAttributable {
|
|||
return insertable && value.hasAnyInsertableColumns();
|
||||
}
|
||||
|
||||
public GeneratorCreator getValueGenerationStrategy() {
|
||||
return generator;
|
||||
@Internal
|
||||
public GeneratorCreator getValueGeneratorCreator() {
|
||||
return generatorCreator;
|
||||
}
|
||||
|
||||
public void setValueGenerationStrategy(GeneratorCreator generator) {
|
||||
this.generator = generator;
|
||||
@Internal
|
||||
public void setValueGeneratorCreator(GeneratorCreator generator) {
|
||||
this.generatorCreator = generator;
|
||||
}
|
||||
|
||||
public void setUpdateable(boolean mutable) {
|
||||
|
@ -284,12 +291,12 @@ public class Property implements Serializable, MetaAttributable {
|
|||
|
||||
/**
|
||||
* Is this property lazy in the "bytecode" sense?
|
||||
*
|
||||
* <p>
|
||||
* Lazy here means whether we should push *something* to the entity
|
||||
* instance for this field in its "base fetch group". Mainly it affects
|
||||
* whether we should list this property's columns in the SQL select
|
||||
* for the owning entity when we load its "base fetch group".
|
||||
*
|
||||
* <p>
|
||||
* The "something" we push varies based on the nature (basic, etc) of
|
||||
* the property.
|
||||
*
|
||||
|
@ -441,6 +448,11 @@ public class Property implements Serializable, MetaAttributable {
|
|||
this.returnedClassName = returnedClassName;
|
||||
}
|
||||
|
||||
public Generator createGenerator(RuntimeModelCreationContext context) {
|
||||
return generatorCreator == null ? null :
|
||||
generatorCreator.createGenerator( new PropertyGeneratorCreationContext( context ) );
|
||||
}
|
||||
|
||||
public Property copy() {
|
||||
final Property prop = new Property();
|
||||
prop.setName( getName() );
|
||||
|
@ -450,7 +462,7 @@ public class Property implements Serializable, MetaAttributable {
|
|||
prop.setInsertable( isInsertable() );
|
||||
prop.setSelectable( isSelectable() );
|
||||
prop.setOptimisticLocked( isOptimisticLocked() );
|
||||
prop.setValueGenerationStrategy( getValueGenerationStrategy() );
|
||||
prop.setValueGeneratorCreator( getValueGeneratorCreator() );
|
||||
prop.setPropertyAccessorName( getPropertyAccessorName() );
|
||||
prop.setPropertyAccessStrategy( getPropertyAccessStrategy() );
|
||||
prop.setLazy( isLazy() );
|
||||
|
@ -464,4 +476,42 @@ public class Property implements Serializable, MetaAttributable {
|
|||
prop.setReturnedClassName( getReturnedClassName() );
|
||||
return prop;
|
||||
}
|
||||
|
||||
private class PropertyGeneratorCreationContext implements GeneratorCreationContext {
|
||||
private final RuntimeModelCreationContext context;
|
||||
|
||||
public PropertyGeneratorCreationContext(RuntimeModelCreationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Database getDatabase() {
|
||||
return context.getMetadata().getDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRegistry getServiceRegistry() {
|
||||
return context.getBootstrapContext().getServiceRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultCatalog() {
|
||||
return context.getSessionFactory().getSessionFactoryOptions().getDefaultCatalog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultSchema() {
|
||||
return context.getSessionFactory().getSessionFactoryOptions().getDefaultSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentClass getPersistentClass() {
|
||||
return persistentClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property getProperty() {
|
||||
return Property.this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.mapping;
|
||||
import org.hibernate.Remove;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
|
@ -13,9 +15,10 @@ import java.io.Serializable;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated This is replaced by {@link org.hibernate.tuple.ValueGeneration} and {@link org.hibernate.tuple.GenerationTiming}
|
||||
* @deprecated This is replaced by {@link org.hibernate.tuple.ValueGeneration} and
|
||||
* {@link org.hibernate.tuple.GenerationTiming}, and is no longer used
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated @Remove
|
||||
public class PropertyGeneration implements Serializable {
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,12 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.mapping;
|
||||
|
||||
import org.hibernate.Remove;
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated this is no longer used
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@Deprecated @Remove
|
||||
public interface SemanticsResolver {
|
||||
CollectionSemantics<?, ?> resolve(org.hibernate.type.CollectionType explicitType);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.Remove;
|
||||
import org.hibernate.TimeZoneStorageStrategy;
|
||||
|
@ -370,10 +371,12 @@ public abstract class SimpleValue implements KeyValue {
|
|||
return (IdentifierGenerator) generator;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public void setCustomIdGeneratorCreator(IdentifierGeneratorCreator customIdGeneratorCreator) {
|
||||
this.customIdGeneratorCreator = customIdGeneratorCreator;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public IdentifierGeneratorCreator getCustomIdGeneratorCreator() {
|
||||
return customIdGeneratorCreator;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,17 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.mapping;
|
||||
import org.hibernate.Remove;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Placeholder for typedef information
|
||||
*
|
||||
* @deprecated no longer used
|
||||
*/
|
||||
@Deprecated @Remove
|
||||
public class TypeDef implements Serializable {
|
||||
|
||||
private String typeClass;
|
||||
|
|
|
@ -13,6 +13,12 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
/**
|
||||
* Instantiator for entities represented as {@link Map}s.
|
||||
*
|
||||
* @deprecated since {@link Instantiator} is deprecated
|
||||
*/
|
||||
@Deprecated(since = "6.2")
|
||||
public class DynamicMapInstantiator implements Instantiator {
|
||||
public static final String KEY = "$type$";
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
|
||||
|
@ -43,10 +42,8 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
|||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tuple.GenerationTiming;
|
||||
import org.hibernate.tuple.Generator;
|
||||
import org.hibernate.tuple.GeneratorCreationContext;
|
||||
import org.hibernate.tuple.IdentifierProperty;
|
||||
import org.hibernate.tuple.InDatabaseGenerator;
|
||||
import org.hibernate.tuple.InMemoryGenerator;
|
||||
|
@ -237,15 +234,15 @@ public class EntityMetamodel implements Serializable {
|
|||
|
||||
List<Property> props = persistentClass.getPropertyClosure();
|
||||
for ( int i=0; i<props.size(); i++ ) {
|
||||
Property prop = props.get(i);
|
||||
Property property = props.get(i);
|
||||
final NonIdentifierAttribute attribute;
|
||||
if ( prop == persistentClass.getVersion() ) {
|
||||
if ( property == persistentClass.getVersion() ) {
|
||||
tempVersionProperty = i;
|
||||
attribute = PropertyFactory.buildVersionProperty(
|
||||
persister,
|
||||
sessionFactory,
|
||||
i,
|
||||
prop,
|
||||
property,
|
||||
bytecodeEnhancementMetadata.isEnhancedForLazyLoading()
|
||||
);
|
||||
}
|
||||
|
@ -254,27 +251,27 @@ public class EntityMetamodel implements Serializable {
|
|||
persister,
|
||||
sessionFactory,
|
||||
i,
|
||||
prop,
|
||||
property,
|
||||
bytecodeEnhancementMetadata.isEnhancedForLazyLoading(),
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
properties[i] = attribute;
|
||||
|
||||
if ( prop.isNaturalIdentifier() ) {
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
naturalIdNumbers.add( i );
|
||||
if ( prop.isUpdateable() ) {
|
||||
if ( property.isUpdateable() ) {
|
||||
foundUpdateableNaturalIdProperty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( "id".equals( prop.getName() ) ) {
|
||||
if ( "id".equals( property.getName() ) ) {
|
||||
foundNonIdentifierPropertyNamedId = true;
|
||||
}
|
||||
|
||||
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
|
||||
prop,
|
||||
property,
|
||||
bytecodeEnhancementMetadata.isEnhancedForLazyLoading(),
|
||||
(entityName) -> {
|
||||
final MetadataImplementor metadata = creationContext.getMetadata();
|
||||
|
@ -306,7 +303,7 @@ public class EntityMetamodel implements Serializable {
|
|||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// generated value strategies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
final Generator generator = buildGenerator( persistentClass, prop, creationContext );
|
||||
final Generator generator = buildGenerator( property, creationContext );
|
||||
generators[i] = generator;
|
||||
if ( generator != null ) {
|
||||
if ( generatedWithNoParameter( generator ) ) {
|
||||
|
@ -369,7 +366,7 @@ public class EntityMetamodel implements Serializable {
|
|||
mutableIndexes.set( i );
|
||||
}
|
||||
|
||||
mapPropertyToIndex(prop, i);
|
||||
mapPropertyToIndex(property, i);
|
||||
}
|
||||
|
||||
if (naturalIdNumbers.size()==0) {
|
||||
|
@ -466,71 +463,27 @@ public class EntityMetamodel implements Serializable {
|
|||
}
|
||||
|
||||
private static Generator buildGenerator(
|
||||
final PersistentClass persistentClass,
|
||||
final Property mappingProperty,
|
||||
final RuntimeModelCreationContext context) {
|
||||
final GeneratorCreator generatorCreator = mappingProperty.getValueGenerationStrategy();
|
||||
final GeneratorCreator generatorCreator = mappingProperty.getValueGeneratorCreator();
|
||||
if ( generatorCreator != null ) {
|
||||
final Generator generator = createGenerator( persistentClass, mappingProperty, context, generatorCreator );
|
||||
final Generator generator = mappingProperty.createGenerator( context );
|
||||
if ( generator.getGenerationTiming().isNotNever() ) {
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
if ( mappingProperty.getValue() instanceof Component ) {
|
||||
Dialect dialect = context.getSessionFactory().getJdbcServices().getDialect();
|
||||
final Dialect dialect = context.getSessionFactory().getJdbcServices().getDialect();
|
||||
final CompositeGeneratorBuilder builder = new CompositeGeneratorBuilder( mappingProperty, dialect );
|
||||
final Component component = (Component) mappingProperty.getValue();
|
||||
for ( Property property : component.getProperties() ) {
|
||||
builder.addPair( createGenerator( null, property, context, property.getValueGenerationStrategy() ) );
|
||||
builder.addPair( property.createGenerator( context ) );
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Generator createGenerator(
|
||||
PersistentClass persistentClass,
|
||||
Property mappingProperty,
|
||||
RuntimeModelCreationContext context,
|
||||
GeneratorCreator generatorCreator) {
|
||||
if ( generatorCreator == null ) {
|
||||
return null;
|
||||
}
|
||||
return generatorCreator.createGenerator(
|
||||
new GeneratorCreationContext() {
|
||||
@Override
|
||||
public Database getDatabase() {
|
||||
return context.getMetadata().getDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRegistry getServiceRegistry() {
|
||||
return context.getBootstrapContext().getServiceRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultCatalog() {
|
||||
return context.getSessionFactory().getSessionFactoryOptions().getDefaultCatalog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultSchema() {
|
||||
return context.getSessionFactory().getSessionFactoryOptions().getDefaultSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentClass getPersistentClass() {
|
||||
return persistentClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property getProperty() {
|
||||
return mappingProperty;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public Generator[] getGenerators() {
|
||||
return generators;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public final class AuditMetadataGenerator extends AbstractMetadataGenerator {
|
|||
private boolean isPropertyInsertable(Property property) {
|
||||
if ( !property.isInsertable() ) {
|
||||
// TODO: this is now broken by changes to generators
|
||||
final GeneratorCreator generation = property.getValueGenerationStrategy();
|
||||
final GeneratorCreator generation = property.getValueGeneratorCreator();
|
||||
if ( generation instanceof GeneratedValueGeneration ) {
|
||||
final GeneratedValueGeneration valueGeneration = (GeneratedValueGeneration) generation;
|
||||
if ( valueGeneration.getGenerationTiming().includesInsert() ) {
|
||||
|
|
Loading…
Reference in New Issue