akku
akku

Reputation: 469

Many-to-many relationship in play framework java

I am trying to use many to many approach product has many to many relation with shop Product.java

package models;
@Entity
public class Product extends Model {

    @Id
    @SequenceGenerator(name="product_gen", sequenceName="product_id_seq", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="product_gen")
    @Column(name="id")
    public Long id;

    @Required
    public String name;

    @Required
    public Float price;

    @ManyToMany(cascade = CascadeType.ALL)
    public List<Shop> shops = new ArrayList<Shop>();

    public Product(String name, float price) {
        this.name = name;
        this.price = price;
    }
    public static List<Product> all(){
        return find.all();
    }
    public static Model.Finder<Long, Product> find = new Model.Finder(Long.class, Product.class);

    public static Product create(String name,float price) {
        Product product = new Product(name, price);
        product.save();
        product.saveManyToManyAssociations("shops");
        return product;
    }




}

play created a table product_shop which has shop_id and product_id as foreign key but not able to store any value in product_shop table on adding a product any help would be appreciated.

Upvotes: 2

Views: 4176

Answers (2)

mgeiger
mgeiger

Reputation: 77

Try looking into an embedded id.

Make a class for your primary key

@Embeddable
public class ProductShopKey {
 public Long productId;
 public Long shopId;

 public boolean equals(Object object) {
  if(object isInstanceOf ProductShopKey){
   ProductShopKey key = (ProductShopKey) object
   if(this.productId == key.productId
      && this.shopId == key.shopId
     ){
        return true;
   }
  }
  return false;
 }

 public int hashCode() {
  return productId.hashCode() + shopId.hashCode();
 }
}

Then make an entity for the class

@entity
public class ProductShop {
 @EmbeddedId
 public ProductShopKey psKey = new ProductShopKey();

 @ManyToOne
 @JoinColumn(name = "product_id")
 public Product product;

 @ManyToOne
 @JoinColumn(name = "shop_id")
 public Shop shop;

 //Extra value to go in your join table
 public String someValue;
 ...
}

Then Shop and Product each have a one to many relationship with ProductShop

Inserting entries into the table is done manually

ProductShop ps = new ProductShop();
ps.psKey.productId = someProductId;
ps.psKey.shopId = someShopId;
ps.someValue = someValue;
ps.save();

Upvotes: -1

Julien D
Julien D

Reputation: 1267

I have Apps and Users. Each app can have several Users, each User can use several Apps.

In your case, you can replace App with Product and User with Shop

Here is my working code under Play! 2.2.2

Evolutions of DB :

create table app_user (
  id                varchar(40) not null,
  constraint pk_fb_user primary key (id)
);

create table app (
  id                    varchar(40) not null,
  name                  text,
  constraint pk_app_id primary key (id)
);

create table membership (
  app_id                varchar(40) not null,
  app_user_id           varchar(40) not null,
  constraint fk_membership_app_id foreign key (app_id) references app,
  constraint fk_membership_app_user_id foreign key (app_user_id) references app_user
);

Model App

@Entity
public class App extends Model {

    @Id
    public UUID id;

    @Column
    public String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "membership")
    public List<User> users;

    ....
}

Model User

@Entity
@Table(name = "app_user")
// user is reserved keyword in DB
public class User extends Model {

    @Id
    public UUID id;

}

I don't need to access Apps of a User so I didn't have an App field in User.

Upvotes: 5

Related Questions