Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate 4.1 with HSQLDB gives 'data exception: string data, right truncation'

I have a very strange problem, got it when I upgraded som deps to the project.

I'm now using following versions:

  • Spring: 3.1.0.RELEASE
  • Hibernate: 4.1.7.Final
  • Hsqldb: 2.2.8 (org.hsqldb)

I THINK the problem has to do something with the file field. (Dbfile.content)

Stacktrace:

javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not insert: [org.project.model.Cv]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1315)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1321)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:843)
    at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy36.persist(Unknown Source)
    at org.project.dao.jpa.GenericDaoJpa.save(GenericDaoJpa.java:49)
    at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy40.save(Unknown Source)
    at org.project.dao.CvDaoTest.updateTest(CvDaoTest.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.exception.DataException: could not insert: [org.project.model.Cv]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:102)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2345)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2852)
    at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
    at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
    at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:837)
    ... 45 more
Caused by: java.sql.SQLDataException: data exception: string data, right truncation
    at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
    at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
    at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
    ... 60 more
Caused by: org.hsqldb.HsqlException: data exception: string data, right truncation
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.types.BinaryType.castOrConvertToType(Unknown Source)
    at org.hsqldb.types.BinaryType.convertToType(Unknown Source)
    at org.hsqldb.StatementDML.getInsertData(Unknown Source)
    at org.hsqldb.StatementInsert.getInsertValuesNavigator(Unknown Source)
    at org.hsqldb.StatementInsert.getResult(Unknown Source)
    at org.hsqldb.StatementDMQL.execute(Unknown Source)
    at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 65 more

Console:

INFO : org.hibernate.engine.jdbc.JdbcSupportLoader - Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
Hibernate: insert into Nationality (id, countryCode) values (default, ?)
Hibernate: insert into Language (id, countryCode, languageCode) values (default, ?, ?)
Hibernate: insert into Person (id, birthdate, created, email, enabled, firstName, image, lastName, lastUpdate, nationality_id, password, role, salt) values (default, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into Nationality (id, countryCode) values (default, ?)
Hibernate: insert into Person (id, birthdate, created, email, enabled, firstName, image, lastName, lastUpdate, nationality_id, password, role, salt) values (default, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into Company (id, name) values (default, ?)
Hibernate: insert into Language (id, countryCode, languageCode) values (default, ?, ?)
Hibernate: insert into Company (id, name) values (default, ?)
Hibernate: insert into Skill (id, company_id, created, isCategory, lastUpdate, skill_fk) values (default, ?, ?, ?, ?, ?)
Hibernate: insert into Company (id, name) values (default, ?)
Hibernate: insert into Skill (id, company_id, created, isCategory, lastUpdate, skill_fk) values (default, ?, ?, ?, ?, ?)
Hibernate: insert into Nationality (id, countryCode) values (default, ?)
Hibernate: insert into Person (id, birthdate, created, email, enabled, firstName, image, lastName, lastUpdate, nationality_id, password, role, salt) values (default, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into CourseExperience (created, lastUpdate, lastUpdatePerson_id, person_fk, endDate, startDate, id) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into Nationality (id, countryCode) values (default, ?)
Hibernate: insert into Person (id, birthdate, created, email, enabled, firstName, image, lastName, lastUpdate, nationality_id, password, role, salt) values (default, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into CourseExperience (created, lastUpdate, lastUpdatePerson_id, person_fk, endDate, startDate, id) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into Cv (id, company, created, language, lastUpdate, lastUpdatePerson_id, name, person_fk, summary_id) values (default, ?, ?, ?, ?, ?, ?, ?, ?)
WARN : org.hibernate.util.JDBCExceptionReporter - SQL Error: -3401, SQLState: 22001
ERROR: org.hibernate.util.JDBCExceptionReporter - data exception: string data, right truncation

Cv.java:

package org.project.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.OrderColumn;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.project.model.interfaces.DomainObject;

@Entity
public class Cv implements DomainObject {

    private static final long serialVersionUID = -9111485038728016755L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @ManyToOne
    @JoinColumn(name = "person_fk")
    private Person person;

    @ManyToMany
    private List<Skill> skills = new ArrayList<Skill>();

    @ManyToOne
    private Summary summary;

    @ManyToMany(targetEntity = Experience.class)
    @OrderColumn(name = "index")
    private List<Experience> experiences = new ArrayList<Experience>();

    @Temporal(TemporalType.TIMESTAMP)
    @Column(updatable = false, insertable = true)
    private Date created;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdate;

    @ManyToOne(optional = false)
    private Person lastUpdatePerson;

    @Column(nullable = false)
    private Language language;

    @Column(nullable = false)
    private Company company;

    @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL, targetEntity = DbFile.class)
    @OrderBy("created DESC")
    private List<DbFile> files = new ArrayList<DbFile>();

    @PrePersist
    @PreUpdate
    protected void updateDates() {
        Date now = new Date();
        if (this.created == null) {
            this.created = new Date(now.getTime());
        }
        this.lastUpdate = now;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public List<Skill> getSkills() {
        return skills;
    }

    public void setSkills(List<Skill> skills) {
        this.skills = skills;
    }

    public List<Experience> getExperiences() {
        return experiences;
    }

    public void setExperiences(List<Experience> experiences) {
        this.experiences = experiences;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(Date lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

    public Person getLastUpdatePerson() {
        return lastUpdatePerson;
    }

    public void setLastUpdatePerson(Person lastUpdatePerson) {
        this.lastUpdatePerson = lastUpdatePerson;
    }

    public void addSkill(Skill skill) {
        this.skills.add(skill);
    }

    public void addExperience(Experience experience) {
        this.experiences.add(experience);
    }

    public Summary getSummary() {
        return summary;
    }

    public void setSummary(Summary summary) {
        this.summary = summary;
    }

    public List<DbFile> getFiles() {
        return files;
    }

    public void setFiles(List<DbFile> files) {
        this.files = files;
    }

    public void addFile(DbFile file) {
        this.files.add(file);
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public Language getLanguage() {
        return language;
    }

    public void setLanguage(Language language) {
        this.language = language;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Cv other = (Cv) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
}

DbFile.java:

package org.project.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.PrePersist;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Type;

import org.project.model.interfaces.DomainObject;

@Entity
public class DbFile implements DomainObject {

    private static final long serialVersionUID = 1974800702358176016L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String filename;

    @Column(nullable = false)
    @Lob
    @Type(type = "org.hibernate.type.MaterializedClobType")
    private byte[] content;

    private String contentType;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(updatable = false)
    private Date created;

    @PrePersist
    protected void updateDates() {
        if (this.created == null) {
            this.created = new Date();
        }
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public Date getCreated() {
        return created;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DbFile other = (DbFile) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
}

Test:

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
...
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class CvDaoTest extends AbstractTest {

    @Autowired
    private CvDao cvDao;

    @Test
    public void updateTest() {
        Cv cv = new Cv();
        cv.setName("test");

        ...
        cv.setLastUpdatePerson(lastUpdatePerson);

        ...
        cv.setPerson(person);
        cv.setCreated(new Date());
        cv.setLastUpdate(new Date());

        cv.setCompany(getCompany());
        cv.setLanguage(getLanguage());

        ...
        cv.addSkill(skill1);
        cv.addSkill(skill2);

        ...
        cv.addExperience(experience1);
        cv.addExperience(experience2);

        cvDao.save(cv).getId();
    }
}

GenericDaoJpa.java

public class GenericDaoJpa<T extends DomainObject> implements GenericDao<T> {

    private Class<T> type;
//  @PersistenceContext
    protected EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public GenericDaoJpa(Class<T> type) {
        super();
        this.type = type;
    }

    @Transactional(readOnly = true)
    public T get(Long id) {
        if (id == null) {
            return null;
        } else {
            return entityManager.find(type, id);
        }
    }

    @SuppressWarnings("unchecked")
    @Transactional(readOnly = true)
    public List<T> getAll() {
        return entityManager.createQuery("select o from " + type.getName() + " o").getResultList();
    }

    @Transactional(readOnly = false)
    public T save(T object) {
        if (object.getId() != null) {
            return entityManager.merge(object);
        } else {
            entityManager.persist(object);
        }
        entityManager.flush();
        return object;
    }

    public T delete(T object) {
        entityManager.remove(object);
        return object;
    }
}

It fails on: 'cvDao.save(cv).getId();'

Datasource using class 'com.mchange.v2.c3p0.ComboPooledDataSource' with driver 'org.hsqldb.jdbcDriver' at url 'jdbc:hsqldb:mem:data'

What have I done wrong?

like image 599
Kronis Avatar asked Oct 13 '12 20:10

Kronis


4 Answers

The problem is with HSQLDialect implementation, which registers sql types in its constructor:

public HSQLDialect() {
    super();

    ...
    registerColumnType( Types.BLOB, "blob($l)" );
    registerColumnType( Types.CLOB, "clob($l)" );
    ...
}

Where $l is taken from column length attribute. But if column length attribute is not set explicitly then it has default value of 255. In such case HSQLDialect creates column as CLOB(255) which is funny for clobs...

1)

One solution is to set column length explicitly with sufficient value.

For example:

@Lob
@Column(length = 10000)
private String text;

But if you want to avoid such artificial constructs, you can modify dialect.

2)

Second solution is to modify HSQLDialect:

package com.extensions.dialect;

import java.sql.Types;
import org.hibernate.dialect.HSQLDialect;

public class MyHsqlDialect extends HSQLDialect {

    public MppHsqlDialect() {
        super();
        registerColumnType(Types.CLOB, "clob");
    }
}

and in hibernate configuration setup new dialect:

hibernate.dialect=com.extensions.dialect.MyHsqlDialect

I use this solution in my integration tests.


Some additional info may be found here:

https://hibernate.atlassian.net/browse/HHH-7541

like image 60
przemek hertel Avatar answered Nov 15 '22 08:11

przemek hertel


The correct answer should be: add length to your @Column annotation, like this:

@Lob
@Column(length = 10000, name = "style")
private String style;
like image 45
Petar Tahchiev Avatar answered Nov 15 '22 09:11

Petar Tahchiev


I've had similar problem. There was plenty of errors: "data exception: string data, right truncation". The resolution was to specify size of big fields. Without that fields will be limited to default size. But that is not all. HSQL doesn't automatically updates database schema. So changes will not apply util you recreate database.

@Column(length = 5 * 1024 * 1024) // five megabytes
private byte[] bytesPreview;
like image 5
yuliskov Avatar answered Nov 15 '22 08:11

yuliskov


Try HSQLDB 2.2.9 or the latest sanpshot as the stack trace looks like an issue that was fixed after 2.2.8.

Maven repository for both snapshots and releases is here:

http://www.hsqldb.org/repos/org/hsqldb/hsqldb/

Also see the answer below. It seems the use of "org.hibernate.type.MaterializedClobType" is common with PostgreSQL. But your field is byte[] and can be represented better as BLOB with HSQLDB.

Retrieve image from blob via Hibernate (not JDBC)

like image 1
fredt Avatar answered Nov 15 '22 07:11

fredt