JPA @JoinTable - Three ID Columns

ⅰ亾dé卋堺 提交于 2019-12-12 21:29:35

问题


I have a situation that is quite similar to the one outlined in this question's diagram: JPA. JoinTable and two JoinColumns, although with different issues.

I have three tables: Function, Group, and Location. Currently, I have a join table set up between Location and Group using @JoinTable. It is @ManyToMany on both sides, and works perfectly fine.

I am attempting to add the constraint that no Location should be associated with more than one Group that has the same Function. So I added a column for Function to my join table in my SQL schema and a uniqueness constraint across the Location and Function columns, like so:

create table function_table (
  id varchar(50),
  primary key(id)
);

create table group_table (
  id varchar(50),
  function_id varchar(50) not null,
  primary key(id)
);

alter table group_table add constraint FK_TO_FUNCTION foreign key (function_id) references function_table;

create table location_table (
  id varchar(50),
  primary key(id)
);

create table group_location_join (
  location_id varchar(50) not null,
  group_id varchar(50) not null,
  function_id varchar(50) not null,
  primary key(location_id, group_id, function_id),
  unique(location_id, function_id)
);

alter table group_location_join add constraint FK_TO_LOCATION foreign key (location_id) references location_table;
alter table group_location_join add constraint FK_TO_GROUP foreign key (group_id) references group_table;
alter table group_location_join add constraint FK_TO_FUNCTION foreign key (function_id) references function_table;

I then attempted to set up the following in my model entities:

@Entity
@Table(name = "function_table")
public class Function {
  @Id
  @Column(name = "id", length = 50)
  private String id;
}

@Entity
@Table(name = "group_table")
public class Group {
  @Id
  @Column(name = "id", length = 50)
  private String id;

  @ManyToOne
  @JoinColumn(name = "function_id", referencedColumnName = "id", nullable = false)
  private Function function;

  @ManyToMany
  @JoinTable(name = "group_location_join",
    joinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id"),
                   @JoinColumn(name = "function_id", referencedColumnName = "function_id")},
    inverseJoinColumns = @JoinColumn(name="location_id", referencedColumnName = "id"))
  private Set<Location> locations;
}

@Entity
@Table(name = "location_table")
public class Location {
  @Id
  @Column(name = "id", length = 50)
  private String id;

  @ManyToMany
  @JoinTable(name = "group_location_join",
    joinColumns = @JoinColumn(name="location_id", referencedColumnName = "id")
    inverseJoinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id"),
                   @JoinColumn(name = "function_id", referencedColumnName = "function_id")})
  private Set<Group> groups;
}

(Obviously, there is more to these entities, but I stripped them down to only the parts relevant to this question.)

This does not work. When I write a simple test to create a Location associated with a Group that is associated with a Function, the minute I try to flush the session to commit the transaction, Hibernate gives me this:

java.lang.ClassCastException: my.package.Group cannot be cast to java.io.Serializable

I think what's happening is that Hibernate is getting confused, throwing up its hands, and saying "I'll just serialize it, send it to the database, and hope it knows what's going on."

When I add implements Serializable and add a serialVersionUID to Group, I then get this:

org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: FUNCTION_ID

I'm not really sure how to proceed at this point, or if perhaps I have already proceeded too far down the wrong path. Maybe I'm not thinking about the SQL correctly, and there is a much easier way to ensure this constraint that doesn't involve all this ridiculousness.

Edit: In my system, the DAOs for the tables involved have no save capabilities. Which means that as long as my constraint is set up in the database, my application doesn't care; it can't insert things that violate the constraint because it can't insert things at all.

Edit 2: I never originally solved the stated problem, and instead simply added a third column in my database schema without touching the Java code, as stated in my first Edit section above. But I have since experimented with creating an explicit join table object with an @Embedded compound key, and it seems to work.


回答1:


You are trying to create a composite primary key. In Hibernate you can do it using the @Embeddable annotation. In the example below you can find the way to use a composite key for two entities.

I believe you can move forward with this example and create your own version of primary key.

Mapping ManyToMany with composite Primary key and Annotation:



来源:https://stackoverflow.com/questions/14899736/jpa-jointable-three-id-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!