I have a web app, using EclipseLink and MySQL for storing data. Some of these data are strings, ie varchars in the DB. In the code of entities, the strings have attributes
You can use a Descriptor PreInsert/PreUpdate event for this, or possibly just use JPA PreInsert and PreUpdate events.
Just check the size of the fields and truncate them in the event code.
If required, you could get the field size from the descriptor's mapping's DatabaseField, or use Java reflection to get it from the annotation.
It would probably be even better to just do the truncation in your set methods. Then you do not need to worry about events.
You may also be able to truncate it on the database, check your MySQL settings, or possible use a trigger.
You can set your database to work in a non strict mode as explained here: Automatically trimming length of string submitted to MySQL
Note that it might cancel other validations too so be careful in what you wish for
If you want to do this on a field-by-field basis rather than globally, then you might be able to make a custom type mapping that truncates the value to the given length before inserting it into the table. Then you can attach the converter to the entity by an annotation like:
@Converter(name="myConverter", class="com.example.MyConverter")
and to the relevant fields via:
@Convert("myConverter")
This is really meant for supporting custom SQL types, but it might work for normal varchar type fields as well. Here is a tutorial on making one of these converters.
I don't know anything about the EclipseLink, but in the Hibernate it's doable - you could make an org.hibernate.Interceptor and in onFlushDirty method modify the object's currentState using entity meta data.
Another option is to declare a constant and reference it everywhere you need that length starting with the @Column annotation itself.
This constant can be then forwarded to a truncate function or a validation function that throw a preventive exception if the passed string is too long. This constant can also be re-used on some other layers such as a UI.
For example:
@Entity
public class MyEntity {
public static final int NAME_LENGTH=32;
private Long id;
private String name;
@Id @GeneratedValue
public Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
@Column(length=NAME_LENGTH)
public String getName() {
return name;
}
public void setName(String name) {
this.name = JpaUtil.truncate(name, NAME_LENGTH);
}
}
public class JpaUtil {
public static String truncate(String value, int length) {
return value != null && value.length() > length ? value.substring(0, length) : value;
}
}
Maybe AOP will help:
Intercept all set method in you JavaBean/POJO, and then get the filed to be set. Check if the field is annotate with @Column
and field type is String
. Then truncate the field if it's too long than length
.