Showing posts with label hibernate. Show all posts
Showing posts with label hibernate. Show all posts

Saturday, June 1, 2013

BLOB/TEXT column 'description' used in key specification without a key length

This post is not about solving some problem. Sadly I don't know hot to solve following problem. There are just work arounds. I have following configuration:
MySQL: 5.5.27
hibernate dialect: org.hibernate.dialect.MySQLInnoDBDialect
hibernate: 3.6.9
In my model I have entity with following attribute:
@Entity
@Table(name = "site")
public class Site extends AbstractEntity {
    
    ...
     
    @Column(unique = true, nullable = true, length = 1024 * 100)
    private String description;
    
    ...
     
}
When I run program follow error appears in logs and table site is not created.
2013-06-01 12:15:24 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaUpdate - 
Unsuccessful: create table site (id_site integer not null auto_increment, description longtext unique, name varchar(250) unique, url_pattern longtext not null unique, id_image integer, primary key (id_site)) ENGINE=InnoDB
2013-06-01 12:15:24 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaUpdate - 
BLOB/TEXT column 'description' used in key specification without a key length
Problem is that column 'description' is marked as unique. In InnoDB maximum length of key could be just 767 characters for a single-byte charset like LATIN1 and only 255 characters for UTF8. Look at possible workarounds:
  1. avoid indexes, don't use unique = true
  2. make column length smaller (255) characters for UTF8
  3. compute hash from long column store in in another column and create index on hash column


If you'll have some other possible solution than please let me know.

Thursday, March 28, 2013

Hibernate collection mapping - inverse="true"

Following image describe simple one to many bidirectional entity mapping
There is Entity Author that have collection of written books.
Relation ship attribute 'inverse' means direction of relation. 'true' say that relation begin at Author's object at collection or many side or relation. Otherwise default value 'false' say that relation starts at one side of relation.

inverse="true"

When inverse is set to 'true' following code will create and persist new book.
Book book = new Book();
author.getBooks().add(book);
save(author);

inverse="false"

Same code from previous example will lead to exception
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Author
 at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
 at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108)
If it should work there have to be extra call for saving of Book instance.
Inverse could appear in case on unidirectional and bidirectional relation. Inverse could be used for all types of collection mapping types.

Object and mapping example details

Author and Book Java object could look like:
public class Author {

    private Integer id;

    private String name;

    private Set<Book> books;

    /**
     * @return the books
     */
    public Set<Book> getBooks() {
        return books;
    }

    /**
     * @param books the books to set
     */
    public void setBooks(Set<Book> books) {
        this.books = books;
    }


   ...

}
Book object could look like:
public class Book {

    private Integer id;
    
    private String name;
    
    private String description;
    
    ...
}
And relation mapping between this two object in Author mapping file usually Author.hbm.xml:
 <set name="books" inverse="true">
  <key column="id_author" not-null="true" foreign-key="book_author"/>
  <one-to-many class="Book" />
 </set>
When it's mapped as bidirectional relation there should be in Book mapping file Book.hbm.xml:
<many-to-one name="author" class="Author" column="id_author" foreign-key="book_author" not-null="true"/>

Friday, January 18, 2013

Hibernate inconsistent mapping problem

I met following exception during changing hibernate mapping. I'm using hibernate 3.2

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: cz.koroptev.cubiculus.core.model.Brick column: id_shape (should be mapped with insert="false" update="false")
 at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:605)
 at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:627)
 at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:645)
 at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:420)
 at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
 at org.hibernate.cfg.Configuration.validate(Configuration.java:1026)
 at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1211)
 at cz.koroptev.cubiculus.core.services.impl.HibernateManagerServiceImpl.(HibernateManagerServiceImpl.java:28)
 ... 47 more
Problem was in inconsistent mapping of relations ship between objects 'Shape' and 'Brick'. Object 'Shape' contain set of bricks mapped as:
  <set name="bricks" lazy="true" order-by="id_brick" >
   <key column="id_shape" not-null="true" />
   <one-to-many class="Brick" />
  </set>
and 'Brick' contains mapping to 'Shape'
  <many-to-one name="shape" class="Shape" column="id_shape"
   foreign-key="brick_shape" not-null="false" />
Problem is that in first mapping is column 'id_shape' mapped as not-null="true" and in second is mapped as not-null="false". This lead to mentioned exception.