下面列出了怎么用org.hibernate.tuple.GenerationTiming的API类实例代码及写法,或者点击链接到github查看源代码。
private ValueGeneration determineValueGenerationStrategy(XProperty property) {
ValueGeneration valueGeneration = getValueGenerationFromAnnotations( property );
if ( valueGeneration == null ) {
return NoValueGeneration.INSTANCE;
}
final GenerationTiming when = valueGeneration.getGenerationTiming();
if ( valueGeneration.getValueGenerator() == null ) {
insertable = false;
if ( when == GenerationTiming.ALWAYS ) {
updatable = false;
}
}
return valueGeneration;
}
public void processInsertGeneratedProperties(
Serializable id,
Object entity,
Object[] state,
SharedSessionContractImplementor session) {
if ( !hasInsertGeneratedProperties() ) {
throw new AssertionFailure( "no insert-generated properties" );
}
processGeneratedProperties(
id,
entity,
state,
session,
sqlInsertGeneratedValuesSelectString,
GenerationTiming.INSERT
);
}
public void processUpdateGeneratedProperties(
Serializable id,
Object entity,
Object[] state,
SharedSessionContractImplementor session) {
if ( !hasUpdateGeneratedProperties() ) {
throw new AssertionFailure( "no update-generated properties" );
}
processGeneratedProperties(
id,
entity,
state,
session,
sqlUpdateGeneratedValuesSelectString,
GenerationTiming.ALWAYS
);
}
public GenerationStrategyPair(
InMemoryValueGenerationStrategy inMemoryStrategy,
InDatabaseValueGenerationStrategy inDatabaseStrategy) {
// perform some normalization. Also check that only one (if any) strategy is specified
if ( inMemoryStrategy == null ) {
inMemoryStrategy = NoInMemoryValueGenerationStrategy.INSTANCE;
}
if ( inDatabaseStrategy == null ) {
inDatabaseStrategy = NoInDatabaseValueGenerationStrategy.INSTANCE;
}
if ( inMemoryStrategy.getGenerationTiming() != GenerationTiming.NEVER
&& inDatabaseStrategy.getGenerationTiming() != GenerationTiming.NEVER ) {
throw new ValueGenerationStrategyException(
"in-memory and in-database value generation are mutually exclusive"
);
}
this.inMemoryStrategy = inMemoryStrategy;
this.inDatabaseStrategy = inDatabaseStrategy;
}
/**
* In case the given annotation is a value generator annotation, the corresponding value generation strategy to be
* applied to the given property is returned, {@code null} otherwise.
*/
private <A extends Annotation> AnnotationValueGeneration<A> getValueGenerationFromAnnotation(
XProperty property,
A annotation) {
ValueGenerationType generatorAnnotation = annotation.annotationType()
.getAnnotation( ValueGenerationType.class );
if ( generatorAnnotation == null ) {
return null;
}
Class<? extends AnnotationValueGeneration<?>> generationType = generatorAnnotation.generatedBy();
AnnotationValueGeneration<A> valueGeneration = instantiateAndInitializeValueGeneration(
annotation, generationType, property
);
if ( annotation.annotationType() == Generated.class &&
property.isAnnotationPresent( javax.persistence.Version.class ) &&
valueGeneration.getGenerationTiming() == GenerationTiming.INSERT ) {
throw new AnnotationException(
"@Generated(INSERT) on a @Version property not allowed, use ALWAYS (or NEVER): "
+ StringHelper.qualify( holder.getPath(), name )
);
}
return valueGeneration;
}
private boolean isValueGenerationRequired(NonIdentifierAttribute attribute, GenerationTiming matchTiming) {
if ( attribute.getType() instanceof ComponentType ) {
final ComponentType type = (ComponentType) attribute.getType();
final ValueGeneration[] propertyValueGenerationStrategies = type.getPropertyValueGenerationStrategies();
for ( int i = 0; i < propertyValueGenerationStrategies.length; i++ ) {
if ( isReadRequired( propertyValueGenerationStrategies[i], matchTiming ) ) {
return true;
}
}
return false;
}
else {
return isReadRequired( attribute.getValueGenerationStrategy(), matchTiming );
}
}
private static GenerationStrategyPair buildGenerationStrategyPair(
final SessionFactoryImplementor sessionFactory,
final Property mappingProperty) {
final ValueGeneration valueGeneration = mappingProperty.getValueGenerationStrategy();
if ( valueGeneration != null && valueGeneration.getGenerationTiming() != GenerationTiming.NEVER ) {
// the property is generated in full. build the generation strategy pair.
if ( valueGeneration.getValueGenerator() != null ) {
// in-memory generation
return new GenerationStrategyPair(
FullInMemoryValueGenerationStrategy.create( valueGeneration )
);
}
else {
// in-db generation
return new GenerationStrategyPair(
create(
sessionFactory,
mappingProperty,
valueGeneration
)
);
}
}
else if ( mappingProperty.getValue() instanceof Component ) {
final CompositeGenerationStrategyPairBuilder builder = new CompositeGenerationStrategyPairBuilder( mappingProperty );
interpretPartialCompositeValueGeneration( sessionFactory, (Component) mappingProperty.getValue(), builder );
return builder.buildPair();
}
return NO_GEN_PAIR;
}
private void add(InMemoryValueGenerationStrategy inMemoryStrategy) {
if ( inMemoryStrategies == null ) {
inMemoryStrategies = new ArrayList<>();
}
inMemoryStrategies.add( inMemoryStrategy );
if ( inMemoryStrategy.getGenerationTiming() != GenerationTiming.NEVER ) {
hadInMemoryGeneration = true;
}
}
private void add(InDatabaseValueGenerationStrategy inDatabaseStrategy) {
if ( inDatabaseStrategies == null ) {
inDatabaseStrategies = new ArrayList<>();
}
inDatabaseStrategies.add( inDatabaseStrategy );
if ( inDatabaseStrategy.getGenerationTiming() != GenerationTiming.NEVER ) {
hadInDatabaseGeneration = true;
}
}
private InDatabaseValueGenerationStrategyImpl(
GenerationTiming timing,
boolean referenceColumnInSql,
String[] referencedColumnValues) {
this.timing = timing;
this.referenceColumnInSql = referenceColumnInSql;
this.referencedColumnValues = referencedColumnValues;
}
public boolean isNaturalIdentifierInsertGenerated() {
// the intention is for this call to replace the usage of the old ValueInclusion stuff (as exposed from
// persister) in SelectGenerator to determine if it is safe to use the natural identifier to find the
// insert-generated identifier. That wont work if the natural-id is also insert-generated.
//
// Assumptions:
// * That code checks that there is a natural identifier before making this call, so we assume the same here
// * That code assumes a non-composite natural-id, so we assume the same here
final InDatabaseValueGenerationStrategy strategy = inDatabaseValueGenerationStrategies[ naturalIdPropertyNumbers[0] ];
return strategy != null && strategy.getGenerationTiming() != GenerationTiming.NEVER;
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER;
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER;
}
protected String generateInsertGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( GenerationTiming.INSERT );
}
protected String generateUpdateGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( GenerationTiming.ALWAYS );
}
private String generateGeneratedValuesSelectString(final GenerationTiming generationTimingToMatch) {
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( "get generated state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
// Here we render the select column list based on the properties defined as being generated.
// For partial component generation, we currently just re-select the whole component
// rather than trying to handle the individual generated portions.
String selectClause = concretePropertySelectFragment(
getRootAlias(),
new InclusionChecker() {
@Override
public boolean includeProperty(int propertyNumber) {
final InDatabaseValueGenerationStrategy generationStrategy
= entityMetamodel.getInDatabaseValueGenerationStrategies()[propertyNumber];
return generationStrategy != null
&& timingsMatch( generationStrategy.getGenerationTiming(), generationTimingToMatch );
}
}
);
selectClause = selectClause.substring( 2 );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuilder()
.append( String.join( "=? and ", aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
return select.setSelectClause( selectClause )
.setFromClause( fromClause )
.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
}
private void processGeneratedProperties(
Serializable id,
Object entity,
Object[] state,
SharedSessionContractImplementor session,
String selectionSQL,
GenerationTiming matchTiming) {
// force immediate execution of the insert batch (if one)
session.getJdbcCoordinator().executeBatch();
try {
PreparedStatement ps = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( selectionSQL );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( ps );
try {
if ( !rs.next() ) {
throw new HibernateException(
"Unable to locate row for retrieval of generated properties: " +
MessageHelper.infoString( this, id, getFactory() )
);
}
int propertyIndex = -1;
for ( NonIdentifierAttribute attribute : entityMetamodel.getProperties() ) {
propertyIndex++;
if ( isValueGenerationRequired( attribute, matchTiming ) ) {
final Object hydratedState = attribute.getType().hydrate(
rs, getPropertyAliases(
"",
propertyIndex
), session, entity
);
state[propertyIndex] = attribute.getType().resolve( hydratedState, session, entity );
setPropertyValue( entity, propertyIndex, state[propertyIndex] );
}
}
// for ( int i = 0; i < getPropertySpan(); i++ ) {
// if ( includeds[i] != ValueInclusion.NONE ) {
// Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity );
// state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
// setPropertyValue( entity, i, state[i] );
// }
// }
}
finally {
if ( rs != null ) {
session.getJdbcCoordinator().getResourceRegistry().release( rs, ps );
}
}
}
finally {
session.getJdbcCoordinator().getResourceRegistry().release( ps );
session.getJdbcCoordinator().afterStatementExecution();
}
}
catch (SQLException e) {
throw getFactory().getSQLExceptionHelper().convert(
e,
"unable to select generated column values",
selectionSQL
);
}
}
/**
* Whether the given value generation strategy requires to read the value from the database or not.
*/
private boolean isReadRequired(ValueGeneration valueGeneration, GenerationTiming matchTiming) {
return valueGeneration != null &&
valueGeneration.getValueGenerator() == null &&
timingsMatch( valueGeneration.getGenerationTiming(), matchTiming );
}
private boolean timingsMatch(GenerationTiming timing, GenerationTiming matchTiming) {
return
( matchTiming == GenerationTiming.INSERT && timing.includesInsert() ) ||
( matchTiming == GenerationTiming.ALWAYS && timing.includesUpdate() );
}
public GenerationStrategyPair buildPair() {
if ( hadInMemoryGeneration && hadInDatabaseGeneration ) {
throw new ValueGenerationStrategyException(
"Composite attribute [" + mappingProperty.getName() + "] contained both in-memory"
+ " and in-database value generation"
);
}
else if ( hadInMemoryGeneration ) {
throw new NotYetImplementedException( "Still need to wire in composite in-memory value generation" );
}
else if ( hadInDatabaseGeneration ) {
final Component composite = (Component) mappingProperty.getValue();
// we need the numbers to match up so we can properly handle 'referenced sql column values'
if ( inDatabaseStrategies.size() != composite.getPropertySpan() ) {
throw new ValueGenerationStrategyException(
"Internal error : mismatch between number of collected in-db generation strategies" +
" and number of attributes for composite attribute : " + mappingProperty.getName()
);
}
// the base-line values for the aggregated InDatabaseValueGenerationStrategy we will build here.
GenerationTiming timing = GenerationTiming.INSERT;
boolean referenceColumns = false;
String[] columnValues = new String[ composite.getColumnSpan() ];
// start building the aggregate values
int propertyIndex = -1;
int columnIndex = 0;
Iterator subProperties = composite.getPropertyIterator();
while ( subProperties.hasNext() ) {
propertyIndex++;
final Property subProperty = (Property) subProperties.next();
final InDatabaseValueGenerationStrategy subStrategy = inDatabaseStrategies.get( propertyIndex );
if ( subStrategy.getGenerationTiming() == GenerationTiming.ALWAYS ) {
// override the base-line to the more often "ALWAYS"...
timing = GenerationTiming.ALWAYS;
}
if ( subStrategy.referenceColumnsInSql() ) {
// override base-line value
referenceColumns = true;
}
if ( subStrategy.getReferencedColumnValues() != null ) {
if ( subStrategy.getReferencedColumnValues().length != subProperty.getColumnSpan() ) {
throw new ValueGenerationStrategyException(
"Internal error : mismatch between number of collected 'referenced column values'" +
" and number of columns for composite attribute : " + mappingProperty.getName() +
'.' + subProperty.getName()
);
}
System.arraycopy(
subStrategy.getReferencedColumnValues(),
0,
columnValues,
columnIndex,
subProperty.getColumnSpan()
);
}
}
// then use the aggregated values to build the InDatabaseValueGenerationStrategy
return new GenerationStrategyPair(
new InDatabaseValueGenerationStrategyImpl( timing, referenceColumns, columnValues )
);
}
else {
return NO_GEN_PAIR;
}
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER;
}
private FullInMemoryValueGenerationStrategy(GenerationTiming timing, ValueGenerator generator) {
this.timing = timing;
this.generator = generator;
}
@Override
public GenerationTiming getGenerationTiming() {
return timing;
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER;
}
@Override
public GenerationTiming getGenerationTiming() {
return timing;
}
public boolean isVersionGenerated() {
final InDatabaseValueGenerationStrategy strategy = inDatabaseValueGenerationStrategies[ versionPropertyIndex ];
return strategy != null && strategy.getGenerationTiming() != GenerationTiming.NEVER;
}
@Override
public GenerationTiming getGenerationTiming() {
return propertyElement.getGenerated();
}
@Override
public GenerationTiming getGenerationTiming() {
return null;
}
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER;
}
@Override
public GenerationTiming getGenerationTiming() {
return basicAttributeMapping.getGenerated();
}