Hibernate.orgCommunity Documentation

Chapter 2. Declaring and validating bean constraints

2.1. Declaring bean constraints
2.1.1. Field-level constraints
2.1.2. Property-level constraints
2.1.3. Type argument constraints
2.1.4. Class-level constraints
2.1.5. Constraint inheritance
2.1.6. Object graphs
2.2. Validating bean constraints
2.2.1. Obtaining a Validator instance
2.2.2. Validator methods
2.2.3. ConstraintViolation methods
2.3. Built-in constraints
2.3.1. Bean Validation constraints
2.3.2. Additional constraints

In this chapter you will learn how to declare (see Section 2.1, “Declaring bean constraints”) and validate (see Section 2.2, “Validating bean constraints”) bean constraints. Section 2.3, “Built-in constraints” provides an overview of all built-in constraints coming with Hibernate Validator.

If you are interested in applying constraints to method parameters and return values, refer to Chapter 3, Declaring and validating method constraints.

Constraints in Bean Validation are expressed via Java annotations. In this section you will learn how to enhance an object model with these annotations. There are the following three types of bean constraints:

If your model class adheres to the JavaBeans standard, it is also possible to annotate the properties of a bean class instead of its fields. Example 2.2, “Property-level constraints” uses the same entity as in Example 2.1, “Field-level constraints”, however, property level constraints are used.


Note

The property’s getter method has to be annotated, not its setter. That way also read-only properties can be constrained which have no setter method.

When using property level constraints property access strategy is used to access the value to be validated, i.e. the validation engine accesses the state via the property accessor method.

Tip

It is recommended to stick either to field or property annotations within one class. It is not recommended to annotate a field and the accompanying getter method as this would cause the field to be validated twice.

Starting from Java 8, it is possible to specify constraints directly on the type argument of a parameterized type. However, this requires that ElementType.TYPE_USE is specified via @Target in the constraint definition. To maintain backwards compatibility, built-in Bean Validation as well as Hibernate Validator specific constraints do not yet specify ElementType.TYPE_USE. To make use of type argument constraints, custom constraints must be used (see Chapter 6, Creating custom constraints).

Hibernate Validator validates type arguments constraints specified on collections, map values, java.util.Optional, and custom parameterized types.

Type arguments constraints can with two restrictions also be used with custom types. First, a ValidatedValueUnwrapper must be registered for the custom type allowing to retrieve the value to validate (see Section 11.11, “Unwrapping values”). Second, only types with one type arguments are supported. Parameterized types with two or more type arguments are not checked for type argument constraints. This limitation might change in future versions.

Example 2.6, “Type argument constraint on custom parameterized type” shows an example of a custom parameterized type with a type argument constraint.

Example 2.6. Type argument constraint on custom parameterized type

package org.hibernate.validator.referenceguide.chapter02.typeargument;

public class Car {

	private GearBox<@MinTorque(100) Gear> gearBox;

	public void setGearBox(GearBox<Gear> gearBox) {
		this.gearBox = gearBox;
	}

	//...
}
package org.hibernate.validator.referenceguide.chapter02.typeargument;

public class GearBox<T extends Gear> {

	private final T gear;

	public GearBox(T gear) {
		this.gear = gear;
	}

	public Gear getGear() {
		return this.gear;
	}
}
package org.hibernate.validator.referenceguide.chapter02.typeargument;

public class Gear {
	private final Integer torque;

	public Gear(Integer torque) {
		this.torque = torque;
	}

	public Integer getTorque() {
		return torque;
	}

	public static class AcmeGear extends Gear {
		public AcmeGear() {
			super( 100 );
		}
	}
}
package org.hibernate.validator.referenceguide.chapter02.typeargument;

public class GearBoxUnwrapper extends ValidatedValueUnwrapper<GearBox> {
	@Override
	public Object handleValidatedValue(GearBox gearBox) {
		return gearBox == null ? null : gearBox.getGear();
	}

	@Override
	public Type getValidatedValueType(Type valueType) {
		return Gear.class;
	}
}
Car car = Car();
car.setGearBox( new GearBox<>( new Gear.AcmeGear() ) );

Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );
assertEquals( 1, constraintViolations.size() );
assertEquals( "Gear is not providing enough torque.", constraintViolations.iterator().next().getMessage() );
assertEquals( "gearBox", constraintViolations.iterator().next().getPropertyPath().toString() );

Last but not least, a constraint can also be placed on the class level. In this case not a single property is subject of the validation but the complete object. Class-level constraints are useful if the validation depends on a correlation between several properties of an object.

The Car class in Example 2.7, “Class-level constraint” has the two attributes seatCount and passengers and it should be ensured that the list of passengers has not more entries than seats are available. For that purpose the @ValidPassengerCount constraint is added on the class level. The validator of that constraint has access to the complete Car object, allowing to compare the numbers of seats and passengers.

Refer to Section 6.2, “Class-level constraints” to learn in detail how to implement this custom constraint.


The Bean Validation API does not only allow to validate single class instances but also complete object graphs (cascaded validation). To do so, just annotate a field or property representing a reference to another object with @Valid as demonstrated in Example 2.9, “Cascaded validation”.


If an instance of Car is validated, the referenced Person object will be validated as well, as the driver field is annotated with @Valid. Therefore the validation of a Car will fail if the name field of the referenced Person instance is null.

The validation of object graphs is recursive, i.e. if a reference marked for cascaded validation points to an object which itself has properties annotated with @Valid, these references will be followed up by the validation engine as well. The validation engine will ensure that no infinite loops occur during cascaded validation, for example if two objects hold references to each other.

Note that null values are getting ignored during cascaded validation.

Object graph validation also works for collection-typed fields. That means any attributes that

  • are arrays
  • implement java.lang.Iterable (especially Collection, List and Set)
  • implement java.util.Map

can be annotated with @Valid, which will cause each contained element to be validated, when the parent object is validated.


So when validating an instance of the Car class shown in Example 2.10, “Cascaded validation of a collection”, a ConstraintViolation will be created, if any of the Person objects contained in the passengers list has a null name.

The Validator interface is the most important object in Bean Validation. The next section shows how to obtain an Validator instance. Afterwards you’ll learn how to use the different methods of the Validator interface.

The Validator interface contains three methods that can be used to either validate entire entities or just single properties of the entity.

All three methods return a Set<ConstraintViolation>. The set is empty, if the validation succeeds. Otherwise a ConstraintViolation instance is added for each violated constraint.

All the validation methods have a var-args parameter which can be used to specify, which validation groups shall be considered when performing the validation. If the parameter is not specified the default validation group (javax.validation.groups.Default) is used. The topic of validation groups is discussed in detail in Chapter 5, Grouping constraints.

Hibernate Validator comprises a basic set of commonly used constraints. These are foremost the constraints defined by the Bean Validation specification (see Table 2.2, “Bean Validation constraints”). Additionally, Hibernate Validator provides useful custom constraints (see Table 2.3, “Custom constraints” and Table 2.4, “Custom country specific constraints”).

Table 2.2, “Bean Validation constraints” shows purpose and supported data types of all constraints specified in the Bean Validation API. All these constraints apply to the field/property level, there are no class-level constraints defined in the Bean Validation specification. If you are using the Hibernate object-relational mapper, some of the constraints are taken into account when creating the DDL for your model (see column "Hibernate metadata impact").

Note

Hibernate Validator allows some constraints to be applied to more data types than required by the Bean Validation specification (e.g. @Max can be applied to strings). Relying on this feature can impact portability of your application between Bean Validation providers.

Table 2.2. Bean Validation constraints

AnnotationSupported data typesUseHibernate metadata impact

@AssertFalse

Boolean, boolean

Checks that the annotated element is false

None

@AssertTrue

Boolean, boolean

Checks that the annotated element is true

None

@DecimalMax(value=,inclusive=)

BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number

Checks whether the annotated value is less than the specified maximum, when inclusive=false. Otherwise whether the value is less than or equal to the specified maximum. The parameter value is the string representation of the max value according to the BigDecimal string representation.

None

@DecimalMin(value=,inclusive=)

BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number

Checks whether the annotated value is larger than the specified minimum, when inclusive=false. Otherwise whether the value is larger than or equal to the specified minimum. The parameter value is the string representation of the min value according to the BigDecimal string representation.

None

@Digits(integer=,fraction=)

BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number

Checks whether the annotated value is a number having up to integer digits and fraction fractional digits

Defines column precision and scale

@Future

java.util.Date, java.util.Calendar, java.time.chrono.ChronoZonedDateTime, java.time.Instant, java.time.OffsetDateTime; Additionally supported by HV, if the Joda Time date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant

Checks whether the annotated date is in the future

None

@Max(value=)

BigDecimal, BigInteger, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number

Checks whether the annotated value is less than or equal to the specified maximum

Adds a check constraint on the column

@Min(value=)

BigDecimal, BigInteger, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the char sequence is evaluated), any sub-type of Number

Checks whether the annotated value is higher than or equal to the specified minimum

Adds a check constraint on the column

@NotNull

Any type

Checks that the annotated value is not null.

Column(s) are not nullable

@Null

Any type

Checks that the annotated value is null

None

@Past

java.util.Date, java.util.Calendar, java.time.chrono.ChronoZonedDateTime, java.time.Instant, java.time.OffsetDateTime; Additionally supported by HV, if the Joda Time date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant

Checks whether the annotated date is in the past

None

@Pattern(regex=,flag=)

CharSequence

Checks if the annotated string matches the regular expression regex considering the given flag match

None

@Size(min=, max=)

CharSequence, Collection, Map and arrays

Checks if the annotated element’s size is between min and max (inclusive)

Column length will be set to max

@Valid

Any non-primitive type

Performs validation recursively on the associated object. If the object is a collection or an array, the elements are validated recursively. If the object is a map, the value elements are validated recursively.

None


Note

On top of the parameters indicated in Table 2.2, “Bean Validation constraints” each constraint has the parameters message, groups and payload. This is a requirement of the Bean Validation specification.

In addition to the constraints defined by the Bean Validation API Hibernate Validator provides several useful custom constraints which are listed in Table 2.3, “Custom constraints”. With one exception also these constraints apply to the field/property level, only @ScriptAssert is a class- level constraint.

Table 2.3. Custom constraints

AnnotationSupported data typesUseHibernate metadata impact

@CreditCardNumber(ignoreNonDigitCharacters=)

CharSequence

Checks that the annotated character sequence passes the Luhn checksum test. Note, this validation aims to check for user mistakes, not credit card validity! See also Anatomy of Credit Card Numbers. ignoreNonDigitCharacters allows to ignore non digit characters. The default is false.

None

@EAN

CharSequence

Checks that the annotated character sequence is a valid EAN barcode. type determines the type of barcode. The default is EAN-13.

None

@Email

CharSequence

Checks whether the specified character sequence is a valid email address. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression flags) which the email must match.

None

@Length(min=,
max=)

CharSequence

Validates that the annotated character sequence is between min and max included

Column length will be set to max

@LuhnCheck(startIndex= ,
endIndex=,
checkDigitIndex=,
ignoreNonDigitCharacters=)

CharSequence

Checks that the digits within the annotated character sequence pass the Luhn checksum algorithm (see also Luhn algorithm). startIndex and endIndex allow to only run the algorithm on the specified sub-string. checkDigitIndex allows to use an arbitrary digit within the character sequence as the check digit. If not specified it is assumed that the check digit is part of the specified range. Last but not least, ignoreNonDigitCharacters allows to ignore non digit characters.

None

@Mod10Check(multiplier=,
weight=,
startIndex=,
endIndex=,
checkDigitIndex=,
ignoreNonDigitCharacters=)

CharSequence

Checks that the digits within the annotated character sequence pass the generic mod 10 checksum algorithm. multiplier determines the multiplier for odd numbers (defaults to 3), weight the weight for even numbers (defaults to 1). startIndex and endIndex allow to only run the algorithm on the specified sub-string. checkDigitIndex allows to use an arbitrary digit within the character sequence as the check digit. If not specified it is assumed that the check digit is part of the specified range. Last but not least, ignoreNonDigitCharacters allows to ignore non digit characters.

None

@Mod11Check(threshold=,
startIndex=,
endIndex=,
checkDigitIndex=,
ignoreNonDigitCharacters=,
treatCheck10As=,
treatCheck11As=)

CharSequence

Checks that the digits within the annotated character sequence pass the mod 11 checksum algorithm. threshold specifies the threshold for the mod11 multiplier growth; if no value is specified the multiplier will grow indefinitely. treatCheck10As and treatCheck11As specify the check digits to be used when the mod 11 checksum equals 10 or 11, respectively. Default to X and 0, respectively. startIndex, endIndex checkDigitIndex and ignoreNonDigitCharacters carry the same semantics as in @Mod10Check.

None

@NotBlank

CharSequence

Checks that the annotated character sequence is not null and the trimmed length is greater than 0. The difference to @NotEmpty is that this constraint can only be applied on strings and that trailing white-spaces are ignored.

None

@NotEmpty

CharSequence, Collection, Map and arrays

Checks whether the annotated element is not null nor empty

None

@Range(min=,
max=)

BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types

Checks whether the annotated value lies between (inclusive) the specified minimum and maximum

None

@SafeHtml(whitelistType= ,
additionalTags=,
additionalTagsWithAttributes=)

CharSequence

Checks whether the annotated value contains potentially malicious fragments such as <script/>. In order to use this constraint, the jsoup library must be part of the class path. With the whitelistType attribute a predefined whitelist type can be chosen which can be refined via additionalTags or additionalTagsWithAttributes. The former allows to add tags without any attributes, whereas the latter allows to specify tags and optionally allowed attributes using the annotation @SafeHtml.Tag.

None

@ScriptAssert(lang=,
script=,
alias=)

Any type

Checks whether the given script can successfully be evaluated against the annotated element. In order to use this constraint, an implementation of the Java Scripting API as defined by JSR 223 ("Scripting for the JavaTM Platform") must part of the class path. The expressions to be evaluated can be written in any scripting or expression language, for which a JSR 223 compatible engine can be found in the class path.

None

@URL(protocol=,
host=,
port=,
regexp=,
flags=)

CharSequence

Checks if the annotated character sequence is a valid URL according to RFC2396. If any of the optional parameters protocol, host or port are specified, the corresponding URL fragments must match the specified values. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression flags) which the URL must match. Per default this constraint used the java.net.URL constructor to verify whether a given string represents a valid URL. A regular expression based version is also available - RegexpURLValidator - which can be configured via XML (see Section 7.2, “Mapping constraints via constraint-mappings) or a ConstraintDefinitionContributor (see Section 11.12.2, “Constraint definitions via ConstraintDefinitionContributor).

None