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
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.
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:
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
Executing Another Application from Java
Static Nested Class in Java, Why
How to Create and Handle Composite Primary Key in JPA
Swingutilities.Invokelater() Why Is It Needed
What Is a Difference Between <? Super E> and <? Extends E>
Integer.Tostring(Int I) VS String.Valueof(Int I)
Java Lambdas 20 Times Slower Than Anonymous Classes
How to Do Arithmetic Operations on the Number Baseclass
Why Does the First Panel Added to a Frame Disappear
Using Mockito with Multiple Calls to the Same Method with the Same Arguments
Double Checked Locking in Singleton
Does Setting Java Objects to Null Do Anything Anymore
How to Use "." as the Delimiter with String.Split() in Java
Aggregation Versus Composition
Green Threads VS Non Green Threads
Maven Error: Could Not Find or Load Main Class Org.Codehaus.Plexus.Classworlds.Launcher.Launcher