Bonjour,

Je tente d'implémenter un système de traductions de certains de mes champs au sein d'une Entity. (Pour info, j'utilise HSQL DB)
Ces champs peuvent potentiellement être traduits dans toutes les langues.

J'ai donc (par exemple) deux Map<code langue ("fr",...), traduction> (qui sont donc des String), une map pour chaque attribut, l'un étant "Name", l'autre "Category".

Une table "Labels" est générée et doit contenir: le code langue ("fr",...), la traduction, et une colonne par attribut qui doit être traduit. Chacune de ces colonne est une Foreign Key vers un "Test" se trouvant dans ma table "Test".

Chaque ligne correspondant à une traduction d'un attribut, je n'aurai donc pour chaque ligne qu'une seule colonne xxx_FK remplie (en fonction de l'attribut).


Mon Entity est la suivante:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
@Entity
@Table(name = "Test")
public class Test implements Serializable
{
    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @CollectionOfElements()
    @JoinTable(name = "Labels", joinColumns = {@JoinColumn(name = "testName_fk", nullable=true)})
    @MapKey(columns = {@Column(name = "language")})
    @Column(name = "label")
    private Map<String, String> mapNameLabels;
 
    @CollectionOfElements()
    @JoinTable(name = "Labels", joinColumns = {@JoinColumn(name = "testCategory_fk", nullable=true)})
    @MapKey(columns = {@Column(name = "language")})
    @Column(name = "label")
    private Map<String, String> mapCategoryLabels;
  ... [getters setters]
 
    /**
     * addNameLabel
     * @param language
     * @param value
     */
    public void addNameLabel(String language, String value)
    {
        getMapNameLabels().put(language, value);
    }
 
    /**
     * addCategoryLabel
     * @param language
     * @param value
     */
    public void addCategoryLabel(String language, String value)
    {
        getMapCategoryLabels().put(language, value);
    }
}

Avec un seul attribut déclaré, par exemple "mapNameLabels", aucun souci, j'ai ma table "Labels" qui est bien générée à chaque fois que je sauve une instance de "Test", et ma table "Labels" contient bien les colonnes suivantes:
"TESTNAME_FK", "LANGUAGE" et "LABEL", avec les traductions ajoutées dans la map.

Problème:
A partir du moment où je déclare une autre map, pour stocker les traductions d'un autre champ, ça pète à l'exécution, à savoir :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 
 
Hibernate: insert into Labels (testName_fk, language, label) values (?, ?, ?)
 14/04/2010 14:54:51,837 WARN [main] JDBCExceptionReporter.logExceptions(100) | SQL Error: 0, SQLState: null
 14/04/2010 14:54:51,847 ERROR [main] JDBCExceptionReporter.logExceptions(101) | failed batch
 14/04/2010 14:54:51,847 ERROR [main] AbstractFlushingEventListener.performExecutions(324) | Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
        at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
        at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:304)
        at org.springframework.orm.jpa.JpaTemplate$8.doInJpa(JpaTemplate.java:295)
        at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:184)
        at org.springframework.orm.jpa.JpaTemplate.flush(JpaTemplate.java:293)
        at domain.dao.impl.TestDAOImpl.saveTest(TestDAOImpl.java:99)
        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy22.saveTest(Unknown Source)
Caused by: java.sql.BatchUpdateException: failed batch
        at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
        at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
        at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:294)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
        ... 24 more
 14/04/2010 14:54:51,887 ERROR [main] TestDAOImpl.saveTest(103) | JDBC exception on Hibernate data access: SQLException for SQL [insert into Labels (testName_fk, language, label) values (?, ?, ?)]; SQL state [null]; error code [0]; Could not execute JDBC batch update; nested exception is org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
 14/04/2010 14:54:51,897 ERROR [main] KPUtils.testPersistance(53) | Error - 
org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access: SQLException for SQL [insert into Labels (testName_fk, language, label) values (?, ?, ?)]; SQL state [null]; error code [0]; Could not execute JDBC batch update; nested exception is org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
        at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:642)
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:95)
        at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:212)
        at org.springframework.orm.jpa.JpaAccessor.translateIfNecessary(JpaAccessor.java:152)
        at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:189)
J'ai bien déclaré mes Foreign Key comme "nullable=true", cependant j'ai l'impression que c'est ça qui fait foirer l'insertion, j'ai l'impression que HSQL attend bien une valeur non nulle pour chacune des Foreign Key.

Auriez-vous une idée ?
Comment puis-je faire fonctionner mon mécanisme ?

Grand merci