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:
Emmanuel Bernard 2009-05-06 15:20:18 +00:00
parent b5a1613827
commit e8dfecb5f7
4 changed files with 78 additions and 49 deletions

View File

@ -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";

View File

@ -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;
// } // }

View File

@ -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 );

View File

@ -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 )
);
}
} }
} }
} }
} }
} }