Je re-précise mon cas :
J'ai par exemple une table TEXT_HOLDER avec les colonnes ID (number), NAME (varchar), I_TXT (number) ; ID étant la pk.
Et une table TXT avec les colonnes I_TXT(number), TXT_ORDER(number), TXT_VALUE(varchar de 250) ; I_TXT et ORDER formant la pk.
Cette table TXT contient des tronçons de texte qui sont réassemblés le cas échéant ; Le texte associé à un TEXT_HOLDER sont tronçonnés (en 250 caractères) et insérés dans la table TXT.
TEXT_HOLDER référence donc la table TXT via sa colonne I_TXT
Dans l'idéal j'aimerais avoir une classe TextHolder qui ressemble à cela :
public class TextHolder
{
private Long mId;
private String mName;
private String mSomeText;
...
}
malheureusement je ne crois pas que cela soit possible...
J'ai donc une classe TextHolder :
Code:
public class TextHolder
{
private Long mId;
private String mName;
private Text mSomeText;
...
}
J'ai également la classe Text :
Code:
public class Text
{
private Long mTextId;
private String mString;
...
}
avec l'implementation UserType qui va avec :
Code:
public class TextUserType implements UserType, ParameterizedType
{
public Object nullSafeGet(ResultSet pRs, String[] pNames, Object pOwner) throws HibernateException, SQLException
{
long textId = pRs.getLong(getTextIdColumnName());
if (pRs.wasNull())
return null;
StringBuffer fullText = new StringBuffer();
Connection conn = pRs.getStatement().getConnection();
PreparedStatement stmt = conn.prepareStatement("select * from TXT where I_TXT=? order by TXT_ORDER");
stmt.setLong(0, textId);
ResultSet rs = stmt.executeQuery();
while (rs.next())
{
fullText.append(rs.getString("TXT_VALUE"));
}
return new SnpsText(new Long(textId), fullText.toString());
}
private String getTextIdColumnName()
{
return mParameters.getProperty(TEXT_ID_COLUMN_NAME);
}
public void nullSafeSet(PreparedStatement pSt, Object pValue, int pIndex) throws HibernateException, SQLException
{
SnpsText text = (SnpsText)pValue;
Connection conn = pSt.getConnection();
PreparedStatement stmt = null;
if (text.getTextId() == null)
{
//obtention d'un nouvel identifiant de text
stmt = conn.prepareStatement("select max(I_TXT) from TXT");
ResultSet rs = stmt.executeQuery();
try
{
if (rs.next())
{
long newId = rs.getLong(1);
[b]text.setTextId(new Long(newId + 1));[/b]
}
else
{
throw new HibernateException("Unable to define an ID for text");
}
}
finally
{
rs.close();
stmt.close();
}
}
else
{
//suppression du text existant
try
{
stmt = conn.prepareStatement("delete from TXT where I_TXT=?");
stmt.setLong(1, text.getId().longValue());
stmt.execute();
}
finally
{
stmt.close();
}
}
try
{
// insertion du text dans la table TXT
stmt = conn.prepareStatement("insert into TXT (I_TXT, TXT_ORDER, TXT_VALUE) values (?, ?, ?)");
if (text.getString().length() <= TEXT_MAX_LENGHT)
{
stmt.setLong(1, text.getId().longValue());
stmt.setInt(2, 1);
stmt.setString(3, text.getString());
stmt.executeUpdate(); }
else
{
String[] array = StringTools.split(text.getString(), TEXT_MAX_LENGHT);
for (int i = 0; i < array.length; i++)
{
stmt.setLong(1, text.getId().longValue());
stmt.setInt(2, i);
stmt.setString(3, array[i]);
stmt.executeUpdate();
}
}
// affecter le statement avec l'id du text référencé
pSt.setLong(pIndex, text.getId().longValue());
}
finally
{
stmt.close();
}
}
...
}
Puis le fichier de mapping suivant :
Code:
<hibernate-mapping package="com.myexample">
<class name="TextHolder" table="TEXT_HOLDER" lazy="true">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="name" column="NAME" />
<property name="someText" column="I_TXT" >
<type name="com.myexample.TextUserType">
<param name="textIdColName">I_TXT</param>
</type>
</property>
</class>
</hibernate-mapping>
Actuellement je rencontre le problème suivant : lorsque dans la méthode nullSafeSet j'affecte un id à mon instance de Text, cela n'est pas reporté à l'instance que je manipule dans ma classe de test :
Code:
session = SessionFactoryHolder.currentSession();
tx = session.beginTransaction();
TextHolder holder = new TextHolder();
holder.setSomeText(new SnpsText("Some text for my example"));
holder.setName("my holder name");
session.save(holder);
tx.commit();
Lorsque j'exécute ce code, holder.getSomeText().getTextId() retourne null... et deux lignes ont été insérée dans ma table TXT au lieu d'une seule.
Merci pour vos lumières