简体   繁体   中英

JPA: Is Map<Entity1,Set<Entity2>> possible?

I don't see an example anywhere so I am not sure this is possible. But basically, I am trying to see if I can bind a field in an entity to

   Map<Skill,Set<Rating>> ratings;


CREATE TABLE Worker (
  ID         BIGINT PRIMARY KEY,

);

CREATE TABLE Skill (
  ID   BIGINT PRIMARY KEY,
  name VARCHAR(32) NOT NULL,
  UNIQUE (name)
);

CREATE TABLE WorkerSkillRating (
  ID       BIGINT PRIMARY KEY,
  WorkerID BIGINT NOT NULL,
  SkillID  BIGINT NOT NULL,
  Rating   INT,
  FOREIGN KEY (WorkerID) REFERENCES Worker (ID),
  FOREIGN KEY (SkillID) REFERENCES Skill (ID),
  FOREIGN KEY (Rating) REFERENCES Rating (ID)
);

CREATE TABLE Rating (
  ID       BIGINT PRIMARY KEY,
  score    TINYINT NOT NULL,
  comments VARCHAR(256)
);

Entities

@Entity
public class Skill {

    @Id
    private Long id;

    private String name;


    public Skill(String name) {
        this();
        this.name = name;
    }

    public Skill() {
        this.id = Math.abs( new Random().nextLong());
    }

}


@Entity
public class Worker {

    @Id
    private Long id;

    // The open question
    public Map<Skill, Set<Rating>> ratings;

}

@Entity
public class Rating {

    @Id
    private Long id;
    private Byte score;
    private String comments;

}

According to the JSR-0038 the JPA spec. When using Map, the following combination are just allowed: Basic Type, Entities and Embeddables.

Map<Basic,Basic> 
Map<Basic, Embeddable> 
Map<Basic, Entity>

Map<Embeddable, Basic> 
Map<Embeddable,Embeddable>
Map<Embeddable,Entity> 

Map<Entity, Basic>
Map<Entity,Embeddable>
Map<Entity, Entity> 

I don't think there is pretty much deal to have a possible mapping in the way that you want but that is out of the specs and most of the providers follow them, I think that mapping is not very common at all.

"worker has many skills and he may have been given many ratings on a single skill. "

Then add to the skill class a Set<Ratings> , instead of nested directly in the map as the value of it.

It might not answer your question with the map but...

It looks like your rating table is unnecessary.

You could instead have

CREATE TABLE Worker (
  ID         BIGINT PRIMARY KEY,
);

CREATE TABLE Skill (
  ID   BIGINT PRIMARY KEY,
  name VARCHAR(32) NOT NULL,
  UNIQUE (name)
);

CREATE TABLE WorkerSkill (
  ID       BIGINT PRIMARY KEY,
  WorkerID BIGINT NOT NULL,
  SkillID  BIGINT NOT NULL,
  score    TINYINT NOT NULL,
  comments VARCHAR(256)
  FOREIGN KEY (WorkerID) REFERENCES Worker (ID),
  FOREIGN KEY (SkillID) REFERENCES Skill (ID)
);

Note I moved the rating information to WorkerSkill table.

Then you can map your entities per below

@Entity
public class Skill {

    @Id
    private Long id;

    private String name;

    // Getter setters const etc

}

@Entity
public class WorkerSkill {

    @Id
    private Long id;

    private int score;

    private String comments;

    @ManyToOne
    private Skill skill;

    @ManyToOne        
    private Worker worker;

    // Getter setters const etc

}


@Entity
public class Worker {

    @Id
    private Long id;

    @OneToMany
    public List<WorkerSkill> workerSkills = new ArrayList<>();

    // Getter setters const etc

}

Then you can access all worker's skill using worker.getWorkerSkill();

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