How to Create and Handle Composite Primary Key in JPA

How to create and handle composite primary key in JPA

You can make an Embedded class, which contains your two keys, and then have a reference to that class as EmbeddedId in your Entity.

You would need the @EmbeddedId and @Embeddable annotations.

@Entity
public class YourEntity {
@EmbeddedId
private MyKey myKey;

@Column(name = "ColumnA")
private String columnA;

/** Your getters and setters **/
}
@Embeddable
public class MyKey implements Serializable {

@Column(name = "Id", nullable = false)
private int id;

@Column(name = "Version", nullable = false)
private int version;

/** getters and setters **/
}

Another way to achieve this task is to use @IdClass annotation, and place both your id in that IdClass. Now you can use normal @Id annotation on both the attributes

@Entity
@IdClass(MyKey.class)
public class YourEntity {
@Id
private int id;
@Id
private int version;

}

public class MyKey implements Serializable {
private int id;
private int version;
}

Composite Key with JPA and Hibernate

If you use DB SEQUENCE as the auto generation type only then composite key can work. Otherwise you have to write custom key generator and assign values to both the fields of your composite key before inserting.

@EqualsAndHashCode.Include
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id_projeto")
private Long idProjeto;

@EqualsAndHashCode.Include
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "ra")
private Long ra;

Define composite primary key on JPA Entity

I believe an embeddable composite key is what you need:

@Entity
public class EmployeeEntity extends BaseEntity {

@Embeddable
static class Pk implements Serializable {
@OneToOne
@JoinColumn(name = "PERSON_ID")
private PersonEntity person;

@OneToOne
@JoinColumn(name = "DEPARTMENT_ID")
private DepartmentEntity department;
}

@Id
private final Pk id;

public EmployeeEntity(DepartmentEntity department, PersonEntity person) {
this.id = new Pk();
this.id.person = person;
this.id.department = department;
}
}

Spring Data JPA - create @Composite key for the three tables

Well, I know what you said, but I don't think it's what you meant. You said

Actually I've three tables, Stock, Category and Product. @ManyToMany relationship between Stock and Category, as well as @ManyToMany relationship between Category and Product.

It helps to think about this abstractly. In Chen notation what you said is

Stock System Diagram 1

However this is probably not what you meant. This is problematic because you will need a new Category entity for every Stock and Product relationship. So, if you have a category of ETF then it will be duplicated for every stock in BobsBestETFs product, in fact for every instantiated relation.

What you meant is probably more along the lines of a Stock and Product relationship with a Category attribute, like so.

Stock Product Diagram 2

This this allows for many products each with many stocks and a specific category attribute for each product/stock relation. The issue you will have with this is that you don't want Category to be an attribute but rather a lookup table of categories, like so:

Stock Product Diagram 3

And I think this is what you are looking for. This should be fairly simple to implement with a composite ID but the examples you are showing seem to be somewhat out of date or unclear. Better to find better examples. This is how I would model the last schema.

@Entity
public class Stock {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
@Data
public class Product {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
public class Category {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
@Data
public class StockProduct {
@EmbeddedId
private StockProductPk id;

@ManyToOne
@MapsId("productId")
private Product product;
@ManyToOne
@MapsId("stockId")
private Stock stock;

@ManyToOne
private Category category;
}
@Embeddable
@Data
public class StockProductPk implements Serializable {
private static final long serialVersionUID = 1L;
private Long stockId;
private Long productId;
}

And as an example to use it:

private void create() {
Category catEtf = new Category();
categoryRepo.save(catEtf);
Stock s1 = new Stock();
stockRepo.save(s1);
Product bobEtfs = new Product();
productRepo.save(bobEtfs);

// create a relationship
StockProduct bs1 = new StockProduct();
bs1.setId(new StockProductPk());
bs1.setProduct(bobEtfs);
bs1.setStock(s1);
bs1.setCategory(catEtf);
stockProductRepo.save(bs1);
}
private void read() {
StockProduct sp1 = new StockProduct();
Product p1 = new Product();
p1.setId(1L);
sp1.setProduct(p1);
List<StockProduct> bobEtfs = stockProductRepo.findAll(Example.of(sp1, ExampleMatcher.matching()));
System.out.println(bobEtfs);
}

JPA composite primary key with reference chain

You can use either an @IdClass or an @EmbeddedId, as both are supported. Since you are already using an @IdClass in Compilation, here is a way to map Answer that also uses an @IdClass:

public class AnswerID {
CompilationID compilation; // matches name of attribute and type of Compilation PK
int question; // matches name of attribute and type of Question PK
}

@Entity
@Table(name = "answer", schema = "gamifiedmarketing")
@IdClass(AnswerID.class)
public class Answer implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@JoinColumns({
@JoinColumn(name="author", referencedColumnName="userId"),
@JoinColumn(name="cTime", referencedColumnName="cTime")
})
@ManyToOne
private Compilation compilation;

@Id
@ManyToOne
@JoinColumn(name= "qid")
private Question question;

@Column(columnDefinition="TEXT", length= 255)
private String body;
}

These are examples of derived identities; and derived identities are discussed (with examples) in the JPA 2.2 spec in section 2.4.1.

How to enforce JPA to use composite primary key index order

I don't know what you mean by "index order" but you are using JPA attribute names in the @Index annotation which is wrong. Use column names like @Index(name = "INDEX1", columnList = "identifier,key,transfer_number")

How to generate id when there are composite keys in entity Spring Boot?

primary key (composite keys) cannot auto generated.



Related Topics



Leave a reply



Submit