Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Properly handling long data in Hibernate

I am getting a data too large problem in hibernate. that is-

Caused by: java.sql.BatchUpdateException: Data truncation: Data too long for column 'FBZipLoc' at row 1 at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1527) at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1065) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195) ... 12 more

Is it possible automatic truncate all field's data. or any other way to handle this problem. but I does not want to check all field's data length because I have more then thousand of fields.

like image 826
Khoyendra Pande Avatar asked Jul 30 '11 08:07

Khoyendra Pande


2 Answers

From what I know there is really no way for Hibernate or MySQL to automatically truncate strings without you adding in the logic to handle this. The reason why I would believe that something like this doesn't exist is that I would never want what I asked to be inserted into a database be different than what really was inserted.

I think your only options are...

  1. Change the column definitions. Make it a larger varchar field or maybe even a text field. Don't spend time building a magic tool when just changing the column definition would fix this in a couple clicks. I recommend doing this!

  2. I could see you using some sort of aspect to intercept the setters and then adjusting the size of the string if it's larger than x length. This would be the quickest why to handle it in your code. If changing the DB isn't an option and you have thousands of fields this would be my next choice.

  3. Build a String util class which can re-size your strings...

    setText(String val){this.text = StringUtil.truncate(val,size);}

[UPDATE] Since you can't really update the database I would recommend an aspect to intercept String setters and check their length it might look like this (syntax may be off and i didn't test this)...

private static final MAX_SIZE_OF_STRINGS = 255;

@Around("execution(* your.package.*.set*(..)) && args(java.lang.String)")
public void checkAroundSetter(final ProceedingJoinPoint pjp)
    throws Throwable {
    Object[] args = pjp.getArgs();
    for (int i = 0; i < args.length; i++) {
        if (args[i] instanceof String && ((String) args[i]).size() > MAX_SIZE_OF_STRINGS) {
            args[i] = ((String)args[i]).subString(0,MAX_SIZE_OF_STRINGS) ;
        }
    }
    pjp.proceed(args);
}

Also, there would be some additional overhead if some layer had to check the defined column size against all the data coming in to the table on each insert.

like image 128
Michael J. Lee Avatar answered Sep 27 '22 18:09

Michael J. Lee


You can use Hibernate interceptor for that. It will allow you to alter your object state right before you save it. You can easily trim your strings based on specific columns or specific types that you save.

like image 22
Alex Gitelman Avatar answered Sep 27 '22 19:09

Alex Gitelman