Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate schema validation fails with MySQL CHAR mapped to String

When using the Hibernate validator to verify that JPA entities match the database schema (typically be setting hibernate.ddl-auto = verify) it will fail when it encounters a MySQL CHAR that has been mapped to a String field.

For example, this MySQL table schema:

CREATE TABLE `item` (
  `id` bigint(20) NOT NULL,
  `name` char(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

May be mapped to a JPA entity like this:

@Entity
public class Item
{
    @Id
    private Long id;

    @Column
    private String name;
}

The verification process will fail with the following exception:

org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [name] in table [item]; found [char (Types#CHAR)], but expecting [varchar(255) (Types#VARCHAR)]

A typical solution to this is to use the Hibernate @Type annotation on the field to specify the column data type, this works well enough to satisfy the validator:

@Column
@Type(type = "char")
private String name;

When you actually issue a query that requires mapping a ResultSet to the entity, you will encounter a different set of exceptions (in this case Spring Data was used to issue the query):

org.springframework.orm.jpa.JpaSystemException: Could not set field value [B] value by reflection : [class com.example.Item.name] setter of com.example.Item.name; nested exception is org.hibernate.PropertyAccessException: Could not set field value [B] value by reflection : [class com.example.Item.name] setter of com.example.Item.name

and

java.lang.IllegalArgumentException: Can not set java.lang.String field com.example.Item.name to java.lang.Character

like image 552
Robert Hunt Avatar asked Aug 25 '17 12:08

Robert Hunt


1 Answers

The solution to these exceptions is to set the column definition in the actual JPA @Column annotation rather than the Hibernate specific @Type annotation:

@Column(columnDefinition = "char")
private String name;

This will satisfy the Hibernate validator without confusing Hibernate into thinking you're actually mapping a Character field.

like image 152
Robert Hunt Avatar answered Nov 09 '22 01:11

Robert Hunt