@Size not applied to history columns

Description

I have some String properties in my JPA model, which have a @Size without any @Column annotation:

Hibernate generates the correct DDL for this property:

But Envers will generate a wrong DDL for this:

As the result I can't store entities with long String properties.

The reason is that Envers generates the metadata before the BeanValidationIntegrator applies its constraints - and no adjustment of the audit columns takes place.

In version 4.1.6 the same model was working.

Environment

Wildfly 10.1.0, hibernate-core 5.0.10, hibernate-validator 5.2.4.Final

Activity

Show:
Tobias Liefke
November 30, 2016, 2:27 PM

Workaround 2: Use an Integrator, which applies the length of the plain column to the audit column:

Chris Cranford
November 30, 2016, 5:27 PM

Workaround 1: Use @Column(length = ...). With the disadvantage that you either need to remove the @Size (which might be used by other Validation-Frameworks) or that you have the same information two times.

You can certainly apply both @Size and @Column annotations on the same property without problems, and more importantly, this guarantees portability and deterministic behavior.

Should you decide to use a different persistence provider, there is no guarantee that the property would have the correct length specified for the DDL statements without explicitly including the @Column annotation. The fact Hibernate can deduce @Size's max value to the @Column's maximum length is a feature provided solely by TypeSafeActivator.
That said, I understand that by providing this proprietary feature, users who wish to take advantage of it do expect it to work.

So while I do err on the side of portability here, I'll check with the team and see what makes the most sense here.

Tobias Liefke
December 1, 2016, 9:02 AM

... this guarantees portability ...

I'm using Envers - which supports (afaik) Hibernate only. So no portability in question.

... and deterministic behavior ...

That's the point: If I use @Size(max = 10) and @Column(length = 5), what will the behavior be? I don't mean of Hibernate, but of the application.
That's the idea behind the generic constraint annotations - to have one source for the constraints of all layers (DRY principle).
I would write something like the TypeSaveActivator for other persistence providers by myself, if they don't support it. What I did for other layers of the application as well.

By the way: I've got an integrator, which applies the maximum length of the enum values to EnumType.STRING columns as well, which is a similar (implicit) constraint.

Anyway: I appreciate that you don't reject this ticket right away. As a workaround exists, I'd would think that this is something with low priority.

Chris Cranford
December 1, 2016, 2:47 PM

I believe you may have misunderstood my concerns about portability and deterministic behavior.

Envers aside for a moment, I was implying that a property solely annotated with @Size(max=1000) would likely lead to another persistence provider (ORM framework) interpreting that as VARCHAR(255). Hibernate adjusting the column's length is a feature that we offer and not something guaranteed by other persistence providers.

While applying both annotations duplicates the length value of 1000 which may not be ideal, it does mean the results are interpreted the same way across persistence providers (aka portable & deterministic).

If I use @Size(max = 10) and @Column(length = 5), what will the behavior be? I don't mean of Hibernate, but of the application.

If we ignore any particular persistence and validation frameworks in question, the expected behavior here would be:

  • Strings with a length of 5 or less would be persisted without any property-specific error.

  • Strings with a length of 6 - 10 characters would throw some persistence exception due to truncation.

  • Strings with a length of 11 or greater would throw a validation exception.

Regardless, we still should fix this so that Envers domain model matches that of ORM. I merely was trying to convey the concerns you could have with portability to another provider, without having to worry with writing any type of adapter code to arrive at the same behavior.

Chris Cranford
January 31, 2017, 9:07 PM
Edited

I'd also like to point out that users who use the IDE tool-chain to generate DDL scripts using the hibernate-tools library will also output table definitions that will specify the length of the column as 255 rather than 1000 based on the user's example. This is because the tool-chain library uses the SchemaExport and SchemaUpdate classes which merely look at the mapping data, which doesn't invoke the Bean Validation Integrator to manipulate the mapping data.

Sorry, what I stated above is only partly correct. It's an issue today for the same reason why Enver's an also an issue, the BV integration occurs at a later phase during boostrap. If we moved the BV integration earlier, basically before Envers contributes it's meta models, then it would be capable of influencing both hibernate-tools and hibernate-envers.

But in the case of hibernate-tools, it would have to make sure that the bean validation provider and supporting classes were available or else it would continue to generate DDL which would report VARCHAR(255).

Assignee

Chris Cranford

Reporter

Tobias Liefke

Fix versions

None

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure