简体   繁体   中英

JPA entity from a table with non-unique id

I want to have an entity

class InkFormula {
    int id;
    Map<Ink, Integer> inkPercents;        
    ...
}

from a single table with such a structure:

┌─────┬────────┬─────────┐
│ id  │ ink_id │ percent │
├─────┼────────┼─────────┤
│  1  │   1    │   50    │
├─────┼────────┼─────────┤
│  1  │   2    │   25    │
├─────┼────────┼─────────┤
│  1  │   3    │   0     │
├─────┼────────┼─────────┤
│  2  │   1    │   100   │
├─────┼────────┼─────────┤
│  2  │   2    │   80    │
└─────┴────────┴─────────┘

where non-unique id must be used to congregate a Map<> from ink_id and percent .

The reason why I need a single entity and a single table is a requirement to have unique constraint id , ink_id so that each formula could not contain repeated inks.

Is that possible with JPA and Hibernate?

I would create a composite primary key InkFormulaId which contains two fields: id and ink_id similar to

@Embeddable
public class InkFormulaId implements Serializable {

    private Integer id;

    private Integer inkId;

    // ...
}

@Entity
public class InkFormula {

    @EmbeddedId
    private InkFormulaId inkFormulaId;

    @ManyToOne
    @MapsId(value = "inkId")
    private Ink ink;

    private Integer percents;

    // ...
}

so each InkFormula represents a single line in your table above with a unique primary key ( id , inkId ) and their percents .

To get the mapping you mentioned above, you would have to SELECT all InkFormula for a single id and then group them by inkId in your Java code.

An alternative solution could be using an @ElementCollection annotation and separating data into two tables:

ink_formula    ink_formula_ink_percent
  ┌───┐    ┌──────────────┬──────┬───────┐
  │id │    │ink_formula_id│ink_id│percent│
  ├───┤    ├──────────────┼──────┼───────┤
  │ 1 │    │       1      │   1  │   20  │
  ├───┤    ├──────────────┼──────┼───────┤
  │ 2 │    │       1      │   2  │   55  │
  ├───┤    ├──────────────┼──────┼───────┤
  . . .    . . . . . . . . . . . . . . . . 

The entity class will then look like

@Entity
public class InkFormula {
    @Id
    @GeneratedValue
    int id;      

    @ElementCollection
    @CollectionTable(
            name="ink_formula_ink_percent",
            joinColumns=@JoinColumn(name="ink_formula_id")
    )
    @MapKeyJoinColumn(name="ink_id")
    @Column(name = "percent")
    private Map<Ink, Integer> inkPercents = new TreeMap<>();

    //...    
}

This setup satisfies the unique InkFormula-Ink requirement but we need a separate table for InkFormula .

Next question is how to ensure the uniqueness of each InkFormula since two InkFormulas with different id s can hold the same values in their inkPercents maps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM