The Bitman
The Bitman

Reputation: 1329

composite primary key which contains a foreign key

I have an entity called UserWithRoles:

@Entity
@Getter
@Setter
public class UserWithRoles implements Serializable
{
  @Id
  @GeneratedValue( strategy = GenerationType.AUTO )
  private int id;

  private String name;

  private String password;

  @OneToMany( mappedBy = "user" )
  private List<UserRole> roles;
}

A UserRole entity:

@Entity
@Getter
@Setter
@IdClass( UserRolePK.class )
@Inheritance( strategy = InheritanceType.JOINED )
@DiscriminatorColumn( name = "roleType", discriminatorType = DiscriminatorType.STRING, length = 10 )
abstract public class UserRole implements Serializable
{
  @Id
  // It should be mapped as a foreign PK by user.id (user field declared below)
  private int userID;

  @Id
  private String roleType;

  @ManyToOne
  @JoinColumn( name="user_id", referencedColumnName = "id" )
  private UserWithRoles user;  
}

The primary key class UserRolePK:

@Data
public class UserRolePK implements Serializable
{
  private int userID;
  private String roleType;  
}

I want to create a composite PK to UserRole: UserWithRoles.id + UserRole.roleType How can I map it to the database? Should I use the UserWithRoles type in the PK class instead of the ID? Is it a good idea at all? Or I just should use normal PK to UserRole? The relation would be something like that between the ClientOrder and ClientOrdetItem entities: (ClientOrder.id + ClientOrderItem.num)

Upvotes: 1

Views: 64

Answers (1)

Brian Vosburgh
Brian Vosburgh

Reputation: 3276

You are using Derived Identity.

You need to change UserRole to look like this:

@Entity
@Getter
@Setter
@IdClass( UserRolePK.class )
@Inheritance( strategy = InheritanceType.JOINED )
@DiscriminatorColumn( name = "roleType", discriminatorType = DiscriminatorType.STRING, length = 10 )
abstract public class UserRole implements Serializable
{    
  @Id
  private String roleType;

  @Id
  @ManyToOne
  @JoinColumn( name="user_id", referencedColumnName = "id" )
  private UserWithRoles user;  
}

That is, get rid of the userID field and add an @Id annotation to the user field.

And change UserRolePK to look like this:

@Data
public class UserRolePK implements Serializable
{
  private int user;
  private String roleType;  
}

That is, change the name of the userID field to user, to match the name of the @Id field in UserRole (but its type must still match the type of the UserWithRoles PK field, id).

Derived identity is discussed in JPA 2.1 spec, section 2.4.1.

Upvotes: 2

Related Questions