1

I have entity called Shop and different types of shops (sport, clothes, tech...). That list of types will probably be predefined. One shop can have multiple types. What is the best way to represent that?

I created two entities Shop and Type.

@Entity
@Table(name = "store")
public class Store {

  @GeneratedValue(strategy = GenerationType.AUTO)
  @Id
  private Long id;

  ...
}

@Entity
@Table(name = "type")
public class Type {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    private String name; //sport, clothes, tech...
}

What type of relationship between these two entities should I use?

stylo1234
  • 35
  • 1
  • 7
  • 2
    Why can a shop have multiple types? Are you meaning that a shop can sell products of different "types"? – Snusmumrikken Jan 03 '16 at 22:12
  • @Snusmumrikken Yes, shop can sell diferrent products, that-s why shop can have multiple types. – stylo1234 Jan 04 '16 at 08:38
  • Okey, hold on. I don't using a "type" captures the concept you are looking for. I will write an answer. – Snusmumrikken Jan 04 '16 at 09:13
  • Why isn't Type an enum? – Neil Stockton Jan 04 '16 at 12:05
  • @NeilStockton If one Shop can have only one Type, I would go with enum, but I'm not sure about ManyToMany relationship with enum. Maybe I try using Type as enum like one of the answers below suggested. – stylo1234 Jan 04 '16 at 12:49
  • If it is an ENUM you don't put a relation, and it simply stores the long/String of the enum in the database ... so it handles ALL situations. Having a class to simply mimic long+String is overkill IMHO – Neil Stockton Jan 04 '16 at 13:29

4 Answers4

1

The Store and Type many to many relationship is linked with a third / join table named STORE_TYPE_MAPS.

Store Entity:

@Entity
@Table(name = "store")
public class Store {

  @GeneratedValue(strategy = GenerationType.AUTO)
  @Id
  private Long id;

 @ManyToMany(fetch = FetchType.LAZY, targetEntity=Type.class)
 @JoinTable(name="STORE_TYPE_MAPS",         
 joinColumns=@JoinColumn(name="STORE_ID"),
 inverseJoinColumns=@JoinColumn(name="TYPE_ID")
 private Set<Type> types;
  //... getter-setter
}
ooozguuur
  • 3,396
  • 2
  • 24
  • 42
  • the `Type` you have here does not conceptually align with what OP is looking for, and such mapping, imho, is not giving a reasonable domain model. – Adrian Shum Jan 04 '16 at 02:08
1

Given that you said Type is probably predefined, it seems more reasonable to model it as enum, and making use of ElementCollection

(I have to admit that I haven't tried to use them both in combination, I believe it should work though :P )

public enum Type {
    SPORT, CLOTHES, TECH
}

public class Shop {
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(
        name="SHOP_TYPE",
        joinColumns=@JoinColumn(name="SHOP_ID")
    )
    @Column(name="TYPE")
    // mapping for enum by usertype or other way, depending on JPA version you are using
    private List<Type> types;
}

Of course, you can model SHOP_TYPE as an entity (e.g. ShopType) if you want more complicated operations on it, but what described above looks to me a more reasonable domain model.


Even you do not want the Type to be predefined (i.e. you can create whatever type in your application), it is still more reasonable to model it as a ManyToMany relationship:

public class Type {
    @Id
    @Column(name="TYPE_ID")
    private Long id

    @Column(name="TYPE_NAME")
    private String name;
}

public class Shop {
    @Id
    @Column(name="SHOP_ID")
    private Long id;

    @ManyToMany
    @JoinTable( 
        name="SHOP_TYPE",
        joinColumns=@JoinColumn(name="SHOP_ID"),
        inverseJoinColumns=@JoinColumn(name="TYPE_ID"))
    private List<Type> types;
}

Just one thing to note: It does not look right to have a Type entity which contains a String as type name, and refer to Shop (as some of the answer suggested). Type should be an entity of itself, and, for example, different shops having CLOTHES type should refer to same CLOTHES entity (unless you view types as some kind of arbitrary tag)

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

If Type is an Entity then make it ManyToMany

@ManyToMany
@JoinTable(name="Store_Type")
private List<Type> types;

also it can be an enum

Community
  • 1
  • 1
Flowy
  • 420
  • 1
  • 5
  • 15
  • If you are certain that you want to be able to assign multiple 'types' to a 'store', this is the best answer. If you only want to assign a single 'type' to a 'store' a 'ManyToOne' relation can be used. – KarlP Jan 03 '16 at 23:56
  • So I decided to go with @ManyToMany relationship between Type and Store (or Shop, I just noticed I called it different in my question) with join table Store_Type. – stylo1234 Jan 04 '16 at 10:00
0

I rather prefer to create a new entity called ShopType, the ManyToMany relationship will be created as explained below.

This new Entity allows you to have extra columns in the join table, "ShopType", (which can't be done with a simple @ManyToMany). For example, you can add this information: "the number of articles of each type in each shop".

The code is as follows:

public class Shop {
    @Id
    @Column(name="SHOP_ID")
    private Long id;

    @OneToMany(mappedBy = "shop", cascade = CascadeType.ALL)
    private List<JoinAchatType> joinShopType = new ArrayList();
}

public class ShopType {
    @ManyToOne
    @JoinColumn(name = "SHOP_ID")
    private Shop shop;

    @ManyToOne
    @JoinColumn(name = "TYPE_ID")
    private Type type;

    private int numberArticle;
}

public class Type {
    @Id
    @Column(name="TYPE_ID")
    private Long id;

    @OneToMany(mappedBy = "type", cascade = CascadeType.ALL)
    private List<JoinAchatType> joinShopType = new ArrayList();
}

For more information check these links:

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
ziMtyth
  • 1,008
  • 16
  • 32