Right, finally I understand what you're after. Actually you can map this in the way you described by creating an entity for the mapping table between markets and languages. Then, a separate mapping table between customers and market-to-language entities.
Here's the sample code. I've used surrogate primary keys for the mapping tables but you could just as well use a composite if it suits your php needs better.
Customer.java
Code:
package test.mappingentity;
import java.util.ArrayList;
import java.util.List;
public class Customer {
private Long id;
private List<MarketToLanguage> marketsToLanguages;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<MarketToLanguage> getMarketsToLanguages() {
return marketsToLanguages;
}
public void setMarketsToLanguages(List<MarketToLanguage> marketsToLanguages) {
this.marketsToLanguages = marketsToLanguages;
}
public void add(MarketToLanguage marketToLanguage ) {
if (marketsToLanguages == null) {
marketsToLanguages = new ArrayList();
}
marketsToLanguages.add(marketToLanguage);
}
}
Customer.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.mappingentity">
<class name="Customer" table="mappingentity_Customer">
<id name="id">
<generator class="native" />
</id>
<bag name="marketsToLanguages"
table="mappingentity_CustomerToMarketToLanguages"
cascade="all-delete-orphan">
<key column="CustomerId"/>
<many-to-many column="MarketToLanguageId" class="MarketToLanguage"/>
</bag>
</class>
</hibernate-mapping>
Language.java
Code:
package test.mappingentity;
public class Language {
private Long id;
private String language;
public Language() {}
public Language(String language) {
this.language = language;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
Language.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.mappingentity">
<class name="Language" table="mappingentity_Language">
<id name="id">
<generator class="native" />
</id>
<property name="language"/>
</class>
</hibernate-mapping>
Market.java
Code:
package test.mappingentity;
import java.util.ArrayList;
import java.util.List;
public class Market {
private Long id;
private String name;
private List<Language> languages;
public Market() {}
public Market(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Language> getLanguages() {
return languages;
}
public void setLanguages(List<Language> languages) {
this.languages = languages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addLanguage(Language language) {
if (languages == null) {
languages = new ArrayList<Language>();
}
languages.add(language);
}
}
Market.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.mappingentity">
<class name="Market" table="mappingentity_Market">
<id name="id">
<generator class="native" />
</id>
<property name="name"/>
<!-- Declare this relationship as many-to-many so hibernate uses the join table but specify unique="true" to make it a one-to-many. See hibernate ref doc section 7.3. Unidirectional associations with join tables
-->
<bag name="languages" table="mappingentity_MarketToLanguages">
<key column="MarketId"/>
<many-to-many column="LanguageId" class="Language" unique="true"/>
</bag>
</class>
</hibernate-mapping>
MarketToLanguage.java
Code:
package test.mappingentity;
public class MarketToLanguage {
private Long id;
private Market market;
private Language language;
public MarketToLanguage() {}
public MarketToLanguage(Market market, Language language) {
this.market = market;
this.language = language;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Market getMarket() {
return market;
}
public void setMarket(Market market) {
this.market = market;
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
}
MarketToLanguage.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.mappingentity">
<class name="MarketToLanguage" table="mappingentity_MarketToLanguages">
<id name="id">
<generator class="native" />
</id>
<many-to-one name="market" column="MarketId"/>
<many-to-one name="language" column="LanguageId"/>
</class>
</hibernate-mapping>
TestIt.java
Code:
package test.mappingentity;
import junit.framework.TestCase;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
public class TestIt extends TestCase {
public void testCreateCustomer() {
Session s = HibernateUtil.getSession();
s.beginTransaction();
Language swedish = new Language( "SV" );
s.save(swedish);
Language french = new Language( "FR" );
s.save(french);
Language english = new Language( "EN" );
s.save(english);
Market sweden = new Market( "SE" );
sweden.addLanguage(swedish);
s.save(sweden);
Market canada = new Market( "CA" );
canada.addLanguage(french);
canada.addLanguage(english);
s.save(canada);
Customer customer = new Customer();
// Create link to sweden/swedish and canada/english
customer.add(findMarketToLanguage(s, sweden, swedish));
customer.add(findMarketToLanguage(s, canada, english));
s.save(customer);
s.getTransaction().commit();
s.close();
}
private MarketToLanguage findMarketToLanguage(Session s, Market market, Language language) {
Criteria criteria = s.createCriteria(MarketToLanguage.class);
criteria.add(Restrictions.eq("market", market))
.add(Restrictions.eq("language", language));
return (MarketToLanguage)criteria.uniqueResult();
}
}
HibernateUtil.java
Code:
package test.mappingentity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory factory;
static {
Configuration config = new Configuration()
.addClass(Language.class)
.addClass(Market.class)
.addClass(Customer.class)
.addClass(MarketToLanguage.class)
// HSQLDB Config
.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
.setProperty("hibernate.connection.username", "sa")
.setProperty("hibernate.connection.password", "")
.setProperty("hibernate.hbm2ddl.auto", "create-drop")
// MYSQL Config
// .setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect")
// .setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")
// .setProperty("hibernate.connection.url", "jdbc:mysql://localhost/test")
// .setProperty("hibernate.connection.username", "root")
// .setProperty("hibernate.connection.password", "password")
// .setProperty("hibernate.hbm2ddl.auto", "create-drop")
.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider")
.setProperty("hibernate.show_sql", "true");
HibernateUtil.setSessionFactory(config.buildSessionFactory());
}
public static synchronized Session getSession() {
if (factory == null) {
factory = new Configuration().configure().buildSessionFactory();
}
return factory.openSession();
}
public static void setSessionFactory(SessionFactory factory) {
HibernateUtil.factory = factory;
}
}