HHH-3898 hibernate.check_nullability (default true)
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@16515 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
b5a1613827
commit
e8dfecb5f7
|
@ -503,6 +503,14 @@ public final class Environment {
|
||||||
*/
|
*/
|
||||||
public static final String JACC_CONTEXTID = "hibernate.jacc_context_id";
|
public static final String JACC_CONTEXTID = "hibernate.jacc_context_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable nullability checking.
|
||||||
|
* Raises an exception if a property marked as not-null is null.
|
||||||
|
* Default to true.
|
||||||
|
*/
|
||||||
|
public static final String CHECK_NULLABILITY = "hibernate.check_nullability";
|
||||||
|
|
||||||
|
|
||||||
public static final String BYTECODE_PROVIDER = "hibernate.bytecode.provider";
|
public static final String BYTECODE_PROVIDER = "hibernate.bytecode.provider";
|
||||||
|
|
||||||
public static final String JPAQL_STRICT_COMPLIANCE= "hibernate.query.jpaql_strict_compliance";
|
public static final String JPAQL_STRICT_COMPLIANCE= "hibernate.query.jpaql_strict_compliance";
|
||||||
|
|
|
@ -95,6 +95,7 @@ public final class Settings {
|
||||||
private boolean strictJPAQLCompliance;
|
private boolean strictJPAQLCompliance;
|
||||||
private boolean namedQueryStartupCheckingEnabled;
|
private boolean namedQueryStartupCheckingEnabled;
|
||||||
private EntityTuplizerFactory entityTuplizerFactory;
|
private EntityTuplizerFactory entityTuplizerFactory;
|
||||||
|
private boolean checkNullability;
|
||||||
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
||||||
// private BytecodeProvider bytecodeProvider;
|
// private BytecodeProvider bytecodeProvider;
|
||||||
|
|
||||||
|
@ -489,7 +490,15 @@ public final class Settings {
|
||||||
this.entityTuplizerFactory = entityTuplizerFactory;
|
this.entityTuplizerFactory = entityTuplizerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// void setComponentTuplizerFactory(ComponentTuplizerFactory componentTuplizerFactory) {
|
public boolean isCheckNullability() {
|
||||||
|
return checkNullability;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckNullability(boolean checkNullability) {
|
||||||
|
this.checkNullability = checkNullability;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void setComponentTuplizerFactory(ComponentTuplizerFactory componentTuplizerFactory) {
|
||||||
// this.componentTuplizerFactory = componentTuplizerFactory;
|
// this.componentTuplizerFactory = componentTuplizerFactory;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,11 @@ public class SettingsFactory implements Serializable {
|
||||||
log.info( "Named query checking : " + enabledDisabled( namedQueryChecking ) );
|
log.info( "Named query checking : " + enabledDisabled( namedQueryChecking ) );
|
||||||
settings.setNamedQueryStartupCheckingEnabled( namedQueryChecking );
|
settings.setNamedQueryStartupCheckingEnabled( namedQueryChecking );
|
||||||
|
|
||||||
|
boolean checkNullability = PropertiesHelper.getBoolean(Environment.CHECK_NULLABILITY, properties, true);
|
||||||
|
log.info( "Check Nullability in Core (should be disabled when Bean Validation is on): " + enabledDisabled(useStatistics) );
|
||||||
|
settings.setCheckNullability(checkNullability);
|
||||||
|
|
||||||
|
|
||||||
// String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
|
// String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
|
||||||
// log.info( "Bytecode provider name : " + provider );
|
// log.info( "Bytecode provider name : " + provider );
|
||||||
// BytecodeProvider bytecodeProvider = buildBytecodeProvider( provider );
|
// BytecodeProvider bytecodeProvider = buildBytecodeProvider( provider );
|
||||||
|
|
|
@ -42,9 +42,11 @@ import org.hibernate.type.Type;
|
||||||
public final class Nullability {
|
public final class Nullability {
|
||||||
|
|
||||||
private final SessionImplementor session;
|
private final SessionImplementor session;
|
||||||
|
private final boolean checkNullability;
|
||||||
|
|
||||||
public Nullability(SessionImplementor session) {
|
public Nullability(SessionImplementor session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
this.checkNullability = session.getFactory().getSettings().isCheckNullability();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Check nullability of the class persister properties
|
* Check nullability of the class persister properties
|
||||||
|
@ -60,60 +62,65 @@ public final class Nullability {
|
||||||
final EntityPersister persister,
|
final EntityPersister persister,
|
||||||
final boolean isUpdate)
|
final boolean isUpdate)
|
||||||
throws PropertyValueException, HibernateException {
|
throws PropertyValueException, HibernateException {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Algorithm
|
* Typically when Bean Validation is on, we don't want to validate null values
|
||||||
* Check for any level one nullability breaks
|
* at the Hibernate Core level. Hence the checkNullability setting.
|
||||||
* Look at non null components to
|
*/
|
||||||
* recursively check next level of nullability breaks
|
if ( checkNullability ) {
|
||||||
* Look at Collections contraining component to
|
/*
|
||||||
* recursively check next level of nullability breaks
|
* Algorithm
|
||||||
*
|
* Check for any level one nullability breaks
|
||||||
*
|
* Look at non null components to
|
||||||
* In the previous implementation, not-null stuffs where checked
|
* recursively check next level of nullability breaks
|
||||||
* filtering by level one only updateable
|
* Look at Collections contraining component to
|
||||||
* or insertable columns. So setting a sub component as update="false"
|
* recursively check next level of nullability breaks
|
||||||
* has no effect on not-null check if the main component had good checkeability
|
*
|
||||||
* In this implementation, we keep this feature.
|
*
|
||||||
* However, I never see any documentation mentioning that, but it's for
|
* In the previous implementation, not-null stuffs where checked
|
||||||
* sure a limitation.
|
* filtering by level one only updateable
|
||||||
*/
|
* or insertable columns. So setting a sub component as update="false"
|
||||||
|
* has no effect on not-null check if the main component had good checkeability
|
||||||
|
* In this implementation, we keep this feature.
|
||||||
|
* However, I never see any documentation mentioning that, but it's for
|
||||||
|
* sure a limitation.
|
||||||
|
*/
|
||||||
|
|
||||||
final boolean[] nullability = persister.getPropertyNullability();
|
final boolean[] nullability = persister.getPropertyNullability();
|
||||||
final boolean[] checkability = isUpdate ?
|
final boolean[] checkability = isUpdate ?
|
||||||
persister.getPropertyUpdateability() :
|
persister.getPropertyUpdateability() :
|
||||||
persister.getPropertyInsertability();
|
persister.getPropertyInsertability();
|
||||||
final Type[] propertyTypes = persister.getPropertyTypes();
|
final Type[] propertyTypes = persister.getPropertyTypes();
|
||||||
|
|
||||||
for ( int i = 0; i < values.length; i++ ) {
|
for ( int i = 0; i < values.length; i++ ) {
|
||||||
|
|
||||||
if ( checkability[i] && values[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
if ( checkability[i] && values[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||||
final Object value = values[i];
|
final Object value = values[i];
|
||||||
if ( !nullability[i] && value == null ) {
|
if ( !nullability[i] && value == null ) {
|
||||||
|
|
||||||
//check basic level one nullablilty
|
//check basic level one nullablilty
|
||||||
throw new PropertyValueException(
|
|
||||||
"not-null property references a null or transient value",
|
|
||||||
persister.getEntityName(),
|
|
||||||
persister.getPropertyNames()[i]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if ( value != null ) {
|
|
||||||
|
|
||||||
//values is not null and is checkable, we'll look deeper
|
|
||||||
String breakProperties = checkSubElementsNullability( propertyTypes[i], value );
|
|
||||||
if ( breakProperties != null ) {
|
|
||||||
throw new PropertyValueException(
|
throw new PropertyValueException(
|
||||||
"not-null property references a null or transient value",
|
"not-null property references a null or transient value",
|
||||||
persister.getEntityName(),
|
persister.getEntityName(),
|
||||||
buildPropertyPath( persister.getPropertyNames()[i], breakProperties )
|
persister.getPropertyNames()[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ( value != null ) {
|
||||||
|
|
||||||
|
//values is not null and is checkable, we'll look deeper
|
||||||
|
String breakProperties = checkSubElementsNullability( propertyTypes[i], value );
|
||||||
|
if ( breakProperties != null ) {
|
||||||
|
throw new PropertyValueException(
|
||||||
|
"not-null property references a null or transient value",
|
||||||
|
persister.getEntityName(),
|
||||||
|
buildPropertyPath( persister.getPropertyNames()[i], breakProperties )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue