michael wrote:
Why would you want to do that? IMHO thats not possible, at least not easily.
My intention is to implement an object, that I only extend if I want to implement a multilingual entity. For example:
Code:
public class Multilingual extends Polyglot {
}
And here is the implementation:DB SCHEMA:Code:
-- My application support only language sensitive locales.
-- Otherwise use VARCHAR(255) instead of CHAR(2)
CREATE TABLE `LOCALE` (
`LOCALE` CHAR(2) NOT NULL PRIMARY KEY
);
CREATE TABLE `POLYGLOT` (
`POLYGLOT_ID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE `POLYGLOT_CONTENT` (
`LOCALE` CHAR(2) NOT NULL,
`POLYGLOT_ID` INTEGER UNSIGNED NOT NULL,
`CONTENT_KEY` VARCHAR(255) NOT NULL,
`CONTENT_VALUE` TEXT NOT NULL,
PRIMARY KEY (`LOCALE`, `POLYGLOT_ID`, `CONTENT_KEY`),
FOREIGN KEY `FK_POLYGLOT_CONTENT_LOCALE` (`LOCALE`)
REFERENCES `LOCALE` (`LOCALE`)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY `FK_POLYGLOT_CONTENT_POLYGLOT` (`POLYGLOT_ID`)
REFERENCES `POLYGLOT` (`POLYGLOT_ID`)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE `MULTILINGUAL` (
`MULTILINGUAL_ID` INTEGER UNSIGNED NOT NULL PRIMARY KEY,
FOREIGN KEY `FK_MULTILINGUAL_POLYGLOT` (`MULTILINGUAL_ID`)
REFERENCES `POLYGLOT` (`MULTILINGUAL_ID`)
ON DELETE CASCADE
ON UPDATE CASCADE
);
MAPPING:Code:
<hibernate-mapping>
<class name="Polyglot" table="POLYGLOT">
<cache usage="transactional"/>
<id access="field" name="polyglotID" type="integer" unsaved-value="null">
<column name="POLYGLOT_ID" not-null="true"/>
<generator class="native"/>
</id>
<map access="field" name="contents" table="POLYGLOT_CONTENT">
<cache usage="transactional"/>
<key column="POLYGLOT_ID"/>
<composite-index class="PolyglotIndex">
<key-property access="field" column="LOCALE" name="locale" type="locale"/>
<key-property access="field" column="CONTENT_KEY" name="key" type="string"/>
</composite-index>
<element column="CONTENT_VALUE" type="string"/>
</map>
<!-- So I implement, for example, a multilingual object 'Multilingual' -->
<joined-subclass name="Multilingual" table="MULTILINGUAL">
<key column="MULTILINGUAL_ID"/>
</joined-subclass>
</class>
</hibernate-mapping>
JAVA:Code:
import java.io.Serializable;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public abstract class Polyglot implements Serializable {
private int polyglotID;
public Map contents = new HashMap();
public boolean equals(Object object) {
if (object == this) {
return true;
} else if (object instanceof Polyglot && object.hashCode() == hashCode()) {
return true;
} else {
return false;
}
}
public int hashCode() {
return polyglotID;
}
public String getString(Locale locale, String key) {
PolyglotIndex index = new PolyglotIndex(locale, key);
String value = (String)contents.get(index);
if (value == null) {
return "";
}
return value;
}
public void setString(Locale locale, String key, String value) {
PolyglotIndex index = new PolyglotIndex(locale, key);
if (!value.equals(contents.get(index))) {
contents.put(index, value);
}
}
public void removeString(Locale locale, String key) {
PolyglotIndex index = new PolyglotIndex(locale, key);
contents.remove(index);
}
}
class PolyglotIndex implements Serializable {
private Locale locale;
private String key;
protected PolyglotIndex() {
}
protected PolyglotIndex(Locale locale, String key) {
this.locale = locale;
this.key = key;
}
public final boolean equals(Object object) {
if (object == this) {
return true;
} else if (object instanceof PolyglotIndex && object.hashCode() == hashCode()) {
return true;
} else {
return false;
}
}
public final int hashCode() {
int hash = locale == null ? 0 : locale.hashCode();
hash = 31 * hash + (key == null ? 0 : key.hashCode());
return hash;
}
}
So I can now use my Multilingual object:
Code:
Multilingual someProduct = new Multilingual();
someProduct.setString(Locale.GERMAN, "NAME", "Buch");
someProduct.setString(Locale.ENGLISH, "NAME", "Book");
someProduct.setString(Locale.GERMAN, "TITLE", "Hibernate in Action");
someProduct.setString(Locale.ENGLISH, "TITLE", "Hibernate in Action");
someProduct.setString(Locale.GERMAN, "DESCRIPTION", "Sehr interessantes Buch!");
mayBeAProduct.setString(Locale.ENGLISH, "DESCRIPTION", "Very interesting book!");
session.save(someProduct);
CONCLUSION:
So long as the given Locale exists in the 'LOCALE' table it works fine. My intention is if a locale does not exists in the 'LOCALE' table to throw an exception by setting a string or if a superuser decide to add or remove a locale to make possible without implement an entity that holds the collection of supported locales to manage locales. Therefore I need a solution that persists 'java.util.Locale' object in the plain table 'LOCALE'.