Ebean and many-to-many relationships - how?

pmichna picture pmichna · Dec 16, 2013 · Viewed 8k times · Source

I created a schema in MySQL Workbench: my schema How do I map this to entities in Ebean in Play Framework? In the tutorials they use approach to write a model class, annotate it with @Entity and let Play generate the SQL script but there is no concern about data types (e.g. how to set limit on VARCHAR).

What about many-to-many relationships? In my case - should I create an entity class UsersScenarios or should I create a Scenario model with some field containing a collection of Users objects and a User model containing a collection of Scenario objects? Or maybe I should genereate the schema in MySQL Workbench and somehow map it in my application?

Please help me, as I don't have any ORM experience.

EDIT: I did a little test with two models:

EntityA.java:

package models;

import java.util.*;

import play.db.ebean.*;
import play.data.validation.Constraints.*;

import javax.persistence.*;

@Entity
public class EntityA extends Model {

        @Id
        public Long id;

        @Required
        public String label;

        @ManyToMany
        public List<EntityB> entitiesB = new ArrayList<EntityB>();

        public static Finder<Long,EntityA> find = new Finder(
                        Long.class, EntityA.class
        );
}

EntityB.java

package models;

import java.util.*;

import play.db.ebean.*;
import play.data.validation.Constraints.*;

import javax.persistence.*;

@Entity
public class EntityB extends Model {

        @Id
        public Long id;

        @Required
        public String label;

        @ManyToMany
        public List<EntityA> entitiesA = new ArrayList<EntityA>();

        public static Finder<Long,EntityB> find = new Finder(
                        Long.class, EntityB.class


   );
}

The generated SQL evolution:

create table entity_a (

id                        bigint auto_increment not null,

label                     varchar(255),

constraint pk_entity_a primary key (id))

;



create table entity_b (

id                        bigint auto_increment not null,

label                     varchar(255),

constraint pk_entity_b primary key (id))

;





create table entity_a_entity_b (

entity_a_id                    bigint not null,

entity_b_id                    bigint not null,

constraint pk_entity_a_entity_b primary key (entity_a_id, entity_b_id))

;



create table entity_b_entity_a (

entity_b_id                    bigint not null,

entity_a_id                    bigint not null,

constraint pk_entity_b_entity_a primary key (entity_b_id, entity_a_id))

;







alter table entity_a_entity_b add constraint fk_entity_a_entity_b_entity_a_01 foreign key (entity_a_id) references entity_a (id) on delete restrict on update restrict;



alter table entity_a_entity_b add constraint fk_entity_a_entity_b_entity_b_02 foreign key (entity_b_id) references entity_b (id) on delete restrict on update restrict;



alter table entity_b_entity_a add constraint fk_entity_b_entity_a_entity_b_01 foreign key (entity_b_id) references entity_b (id) on delete restrict on update restrict;



alter table entity_b_entity_a add constraint fk_entity_b_entity_a_entity_a_02 foreign key (entity_a_id) references entity_a (id) on delete restrict on update restrict;

So it seems the evolution script is not perfect - why do I need two tables connecting EntityA and EntityB?

Answer

Leo picture Leo · Dec 16, 2013

With ManyToMany relationship you need to define the owner of the relationship.

In your case it should be like this:

@ManyToMany(mappedBy = "entitiesA")
public List<EntityB> entitiesB = new ArrayList<EntityB>();

With mappedBy it will generate only one bridge table.

Also take a look at these questions, they will give you more understanding:

How do I describe a bridge table to Ebean?

How do I define multiple conditions on a join JPA/Ebean