Why does Hibernate Tools hbm2ddl generation not take into account Bean Validation annotations?
Asked Answered
F

2

4

Summary: I'm using Hibernate Tools 4.0.0-CR1 and Hibernate 4.2 (including Hibernate Validator), but Bean Validations are not picked up. The schema is properly generated when deploying with hibernate.hbm2ddl.auto=create-drop.

But I prefer to generate my DDL via the following build.xml target:

<target name="schemaexport" depends="jar" description="Exports a generated schema to DB and files">
    <path id="lib.path">
        <fileset refid="lib" />
        <pathelement location="${jboss.home}/modules/org/apache/xerces/main/xercesImpl-2.9.1-jbossas-1.jar"/>
        <pathelement location="${jar.dir}" />
    </path>

    <taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask"
             classpathref="lib.path"/>

    <hibernatetool destdir="${basedir}">
        <classpath refid="lib.path"/>
        <jpaconfiguration persistenceunit="TIC" propertyfile="hibernate-console.properties" />
        <hbm2ddl outputfilename="${dist.dir}/db_ddl.sql" format="true"/>
    </hibernatetool>

    <concat destfile="${dist.dir}/tic.sql" fixlastline="yes">
        <filelist dir="${dist.dir}" files="db_ddl.sql" />
        <filelist dir="${jar.dir}" files="import.sql" />
    </concat>
</target>

My hibernate-console.properties is as follows:

hibernate.connection.password=tic
hibernate.connection.username=tic
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.url=jdbc:postgresql://127.0.0.1:5432/db

hibernate.connection.provider_class=org.hibernate.connection.DriverManagerConnectionProvider
hibernate.datasource=
hibernate.transaction.manager_lookup_class=

I double-checked that the jars are in my lib.path...

A sample entity looks like this:

@Entity
public class Title implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(max = 50) @NotEmpty @Column(length = 50)
    private String titlename;

    @Size(max = 50)
    private String shortTitle;
}

The problem here is that hbm2ddl generates a proper "varchar(50)" for "titlename" but a generic "varchar(255)" for "shortTitle". I encountered similar problems with @NotNull and basically every other bean validation annotation. According to the manual this should just work[tm]. What am I doing wrong?

Fancied answered 1/7, 2013 at 6:45 Comment(0)
N
3

You need to distinguish validation api and java persistence api (jpa) (and vendor specific persistence api). Hibernate take into account JPA configuration (and hibernate persistence api) and when you do not provide such configuration then Convention Over Configuration principle is involved to this process. It is why you get varchar(255) for

@Size(max = 50)
private String shortTitle;

it equals to (i omitted other default values)

@Size(max = 50)
@Column(length = 255, nullable = true)
private String shortTitle;

Validation api is involved for validation purposes. To check if the fields properly filled. There can be exist the different validation rules for the same field.


Updated

I mean this http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition-groups.

For one group you validate one constraint, for other group you validate other constraint.

For example

@NotNull(groups = DefaultGroup.class)
@Null(groups = SecondGroup.class)
private String shortTitle;

and then

    Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    Set<ConstraintViolation<Title>> constraintViolations = validator.validate(title, DefaultGroup.class);
    Set<ConstraintViolation<Title>> secondConstraintViolations = validator.validate(title, SecondGroup.class);
Neutrino answered 10/1, 2016 at 3:4 Comment(2)
I think my beef with hibernate is that it also provides the default implementation for bean validation. Can you provide a source for the "there can be different validation rules for a field" thing? My reasoning was that if hibernate knows this field can never contain more than 50 chars, why generate a wider one?Fancied
Ah, so you're saying validation rules are not absolute so the ddl generator can not rely on them. Didn't know this, good point.Fancied
M
-1

Try removing @Size(max=50), use @Column(length = 50) only. Also add @Column(length = 50) to variable shortTitle.

@NotEmpty @Column(length = 50)
private String titlename;

/** User visible short version of the title. */
@Column(length = 50)
private String shortTitle;
Merozoite answered 1/7, 2013 at 8:36 Comment(2)
Thanks for catching the c&p fail. I should probably state it more clearly: I want Hibernate Tools to pick up the validation annotations (they need to stay there for bean validation), like the hibernate manual says it does. I'm confused on why hibernate (core) respects them and hibernate tools doesn't.Fancied
I ran into this issue as well. Looks like the generated DDL does not use JSR-303 annotations as specified in the manual. Did you find a solution?Lorusso

© 2022 - 2024 — McMap. All rights reserved.