Many-to-Many Association with Extra Columns - java

I am not able to map correctly even following all the steps provided in:
https://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
CREATE TABLE `tb_pla_playlist` (
`id_playlist` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`nm_playlist` VARCHAR(10) NOT NULL,
PRIMARY KEY (`id_playlist`) USING BTREE,
)
CREATE TABLE `tb_mid_midia` (
`id_midia` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`nm_midia` VARCHAR(10) NOT NULL,
PRIMARY KEY (`id_midia`) USING BTREE
)
CREATE TABLE `tb_mip_midia_playlist` (
`id_midia` INT(10) UNSIGNED NOT NULL,
`id_playlist` INT(10) UNSIGNED NOT NULL,
`nr_ordem` INT(10) UNSIGNED NOT NULL,
`CREATED_BY` VARCHAR(10) NOT NULL,
PRIMARY KEY (`id_midia`,`CATEGORY_ID`),
CONSTRAINT `FK_id_midia` FOREIGN KEY (`id_midia`)
REFERENCES `midia` (`id_midia`),
CONSTRAINT `FK_id_playlist` FOREIGN KEY (`id_playlist`)
REFERENCES `playlist` (`id_playlist`)
)
playlist.java
#Entity
#Table(name="tb_pla_playlist")
public class Playlist implements Serializable {
private Set<MidiaPlaylist> midiaPlaylist = new HashSet<MidiaPlaylist>();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id_playlist")
private Long idPlaylist;
#OneToMany(mappedBy = "id.playlist", cascade = CascadeType.ALL)
private Set<MidiaPlaylist> getMidiaPlaylist(){
return midiaPlaylist;
}
...
}
[erro: In attribute 'midiaPlaylist', the "mapped by" value 'id.playlist' cannot be resolved to an attribute on the target entity.]
midia.java
#Entity
#Table(name="tb_mid_midia")
public class Midia implements Serializable {
private Set<MidiaPlaylist> midiaPlaylist = new HashSet<MidiaPlaylist>();
#Id
#GeneratedValue
#Column(name="id_midia")
private Long idMidia;
#OneToMany(mappedBy = "id.midia", cascade=CascadeType.ALL)
public Set<MidiaPlaylist> getMidiasPlaylist() {
return midiaPlaylist;
}
[erro: In attribute 'midiasPlaylist', the "mapped by" value 'id.midia' cannot be resolved to an attribute on the target entity.]
MidiaPlaylistPK.java
#Embeddable
public class MidiaPlaylistPK implements Serializable {
private Midia midia;
private Playlist playlist;
#ManyToOne(cascade = CascadeType.ALL)
public Midia getMidia(){
return midia;
}
public void setMidia(Midia midia){
this.midia = midia;
}
#ManyToOne(cascade = CascadeType.ALL)
public Playlist getPlaylist(){
return playlist;
}
public void setPlaylist(Playlist playlist){
this.playlist = playlist;
}
}
MidiaPlaylist.java
#Entity
#Table(name="tb_mip_midia_playlist")
#AssociationOverrides({
#AssociationOverride(name="id.playlist", [erro: Persistent type of override attribute "id.playlist" cannot be resolved]
joinColumns = #JoinColumn(name = "id_playlist")),
#AssociationOverride(name="id.midia", [erro: Persistent type of override attribute "id.midia" cannot be resolved]
joinColumns = #JoinColumn(name = "id_midia"))
})
public class MidiaPlaylist implements Serializable {
private MidiaPlaylistPK id = new MidiaPlaylistPK();
private int nrOrdem;
#EmbeddedId [erro: Embedded ID class should not contain relationship mappings]
public MidiaPlaylistPK getId() {
return this.id;
}
#Column(name="nr_ordem", nullable=false)
public int getNrOrdem(){
return this.nrOrdem;
}
#Transient
public Midia getMidia(){
return getId().getMidia();
}
#Transient
public Playlist getPlaylist(){
return getId().getPlaylist();
}
Relational model
Can someone help me with these errors? Ty!

You should remove #ManyToOne anotation in #Embeddable and use #MapId anotation insted of #Transient, there is an example here:
http://www.objectdb.com/api/java/jpa/MapsId

Related

How to map a OneToOne with ZeroOrOneToOne back reference in JPA?

I have a legacy app which has an entity relationship that looks like this. I changed the names of the fields to less realistic values and reduced to only the relevant fields.
CREATE TABLE `billing_target` (
`billingTargetID` int(11) NOT NULL,
`targetType` char(5) NOT NULL,
`targetID` int(11) NOT NULL
PRIMARY KEY (`billingTargetID`)
);
CREATE TABLE `Client` (
`clientID` int(11) NOT NULL,
`name` varchar(200),
`color` varchar(200),
`shape` varchar(200)
PRIMARY KEY (`clientID`),
CONSTRAINT `fk_client_billingTarget`
FOREIGN KEY (`clientID`)
REFERENCES `billing_target` (`targetID`)
);
My most current attempt which causes an issue when saving as it gives a null entity key exception.
#Data
#Entity
public class BillingTarget implements Serializable {
#Id
#Column(name = "billingTargetID")
private Integer id;
#Column(name = "targetID", nullable = false)
private Integer targetID;
#Column(name = "targetType", nullable = false)
private String type;
}
#Data
#Entity
public class Client implements Serializable {
#Id
#Column(name = "clientID")
private Integer id;
#OneToOne
#JoinColumn(name = "clientID")
#MapsId("targetID")
private BillingTarget billingTarget;
private String name;
private String color;
private String shape;
}
Here's the PlantUML code if interested
#startuml
hide circle
entity BillingTarget {
* billingTargetID <<generated>>
--
* targetType
* targetID <<unique>>
}
entity Client {
* clientID <<fk>>
--
* name
color
shape
}
BillingTarget ||--o| Client : "targetID:clientID"
#enduml
I was already thinking of using a MappedSuperclass but right now it is only one type (though it could be more). Second the billing target may be zero and not null as there's a NOT NULL constraint already present.

Why this Hibernate Relation isn't working?

I try to Connect Pizzas and Ingredients in a n:m relation while all Pizzas have Ingredients as an Attribute List of Ingredients. But in the Relationstable when I create a new Pizza and try to commit there is an Error with the PizzaID in the Relationtable.
The relational Table:
CREATE TABLE `Pizza_Ingredience_Relation` (
`PizzaID` int(11) NOT NULL,
`IngredientID` int(11) NOT NULL,
`Amount` int(11) NOT NULL,
`Volume_Unit` varchar(1) NOT NULL,
PRIMARY KEY (`PizzaID`,`IngredientID`),
KEY `FKc58en2gx5a8n1swmu9tda345` (`IngredientID`),
CONSTRAINT `FK_IngredienceId` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
CONSTRAINT `FKc58en2gx5a8n1swmu9tda345` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
CONSTRAINT `FKhghfxg8raskdydyu8o8msxtfn` FOREIGN KEY (`PizzaID`) REFERENCES `Pizza` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The Ingredient Table:
CREATE TABLE `Zutatenliste` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The Pizza Table:
CREATE TABLE `Pizza` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
`PreisKlein` double NOT NULL,
`PreisMittel` double NOT NULL,
`PreisGroß` double NOT NULL,
`PreisFamilie` double NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
I have two hibernate Entitites, one is a Pizza Entitiy and one the Ingredient Entitiy:
package Model.PizzenDB.SQLConnectionClasses.MySQL;
import Model.PizzenDB.Pizza;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.Where;
import javax.persistence.*;
import java.util.LinkedList;
import java.util.Set;
#Entity
#Table(name = "Pizza")
public class MySQLPizzaHibernateEntity {
#Id
#Column(name = "ID")
private int id;
#Column(name = "Name")
private String name;
#Column(name = "PreisKlein")
private double smallPrice;
#Column(name = "PreisMittel")
private double middlePrice;
#Column(name = "PreisGroß")
private double bigPrice;
#Column(name = "PreisFamilie")
private double familyPrice;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(
name = "Pizza_Ingredience_Relation",
joinColumns = { #JoinColumn(name = "PizzaID", referencedColumnName = "ID") },
inverseJoinColumns = { #JoinColumn(name = "IngredientID") }
)
private Set<MySQLIngredientWithAmountHibernateEntity> ingredience;
public MySQLPizzaHibernateEntity(String name, double smallPrice, double middlePrice, double bigPrice, double familyPrice) {
this.name = name;
this.smallPrice = smallPrice;
this.middlePrice = middlePrice;
this.bigPrice = bigPrice;
this.familyPrice = familyPrice;
}
public MySQLPizzaHibernateEntity() {
}
}
#Entity
#Table(name = "Zutatenliste")
#SecondaryTable(name = "Pizza_Ingredience_Relation", pkJoinColumns = #PrimaryKeyJoinColumn(name = "IngredientID", referencedColumnName = "ID"))
public class MySQLIngredientWithAmountHibernateEntity {
#Id
#Column(name = "ID")
private int id;
#Column(name = "Name")
private String name;
#Column(table = "Pizza_Ingredience_Relation", name="Amount")
private int amount;
#Column(table = "Pizza_Ingredience_Relation", name = "Volume_Unit")
private char unit;
public MySQLIngredientWithAmountHibernateEntity(String name) {
this.name = name;
}
public MySQLIngredientWithAmountHibernateEntity() {
this("");
}
}
I get the following error message:
20:41:45 [main] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] ERROR - Field 'PizzaID' doesn't have a default value
20:41:45 [main] [org.hibernate.internal.ExceptionMapperStandardImpl] ERROR - HHH000346: Error during managed flush [org.hibernate.exception.GenericJDBCException: could not execute statement]
I'm not sure what is wrong in detail I guess it has todo with the PizzaID Foreign Key and that it isn't set properly.
For many to many relationship, you are using middle table with extra columns and you need Embeddable key for that which would comprise of Pizza and Ingredient object (names shortened). Something like:
#Embeddable
public class PizzaIngredientPk {
private MySQLPizzaHibernateEntity pizza;
private MySQLIngredientWithAmountHibernateEntity ingredient;
#ManyToOne
public MySQLPizzaHibernateEntity getPizza() {
return pizza;
}
public void setPizza(MySQLPizzaHibernateEntity pizza) {
this.pizza = pizza;
}
#ManyToOne
public MySQLIngredientWithAmountHibernateEntity getIngredient() {
return ingredient;
}
public void setIngredientID(MySQLIngredientWithAmountHibernateEntity ingredient) {
this.ingredient = ingredient;
}
}
Then this would act as Embedded Key in MySQLIngredientWithAmountHibernateEntity as
#EmbeddedId
PizzaIngredientPk pk = new PizzaIngredientPk();
But this won't work with Secondarytable which is used for one-to-one relationship. #SecondaryTable requires mapping to be with a primary key but in this case Embedded ID would become PK. In fact, you have flaw in your design. You are trying to make one side of your many to many relationship as one-to-one.
As per JPA docs There must be only one EmbeddedId annotation and no Id annotation when the EmbeddedId annotation is used.
Try to specify to Hibernate automatically produce primary keys. Put this annotation above your Id fields and re-create your database.
#GeneratedValue(strategy = GenerationType.IDENTITY)
See: https://thoughts-on-java.org/hibernate-tips-use-auto-incremented-column-primary-key/

How to cascade insert

UPDATE 2014-01-29: I have changed relationshis so entity code and error changed too
I have to store some data in a database and my relations are like this:
Order3d 1-----* Draw 1-----* Line
I want to save everything like this:
Order3d o=new Order3d();
//add data to order (lines and draws)
Session s=HibernateUtils.getSessionFactory().openSession();
s.save(o);
s.close();
I don't have runtime error but now my line is not inserted (only order3d and drawfile are saved)
here are my entities (obviously, they are POJO so I didn't copy getters and setters):
#Entity
#Table (name="order3d")
public class Order3d implements Serializable {
private static final long serialVersionUID = -2241346447352903470L;
public enum State {DEMAND, ESTIMATED, PAYED, PENDING, PRODUCED, SENT, DELIVERED};
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name="id")
private int id;
#Column (name="person")
private int person;
#Column (name="state", columnDefinition="smallint")
private State state;
#Column (name="labor_expense")
private float laborExpense=0;
#Column (name="travel_expense")
private float travelExpense=0;
#Column (name="validity_date")
private Date validityDate;
#Column (name="demand_date")
private Date demandDate;
#Column (name="estimate_date")
private Date estimateDate;
#Column (name="order_date")
private Date orderDate=null;
#Column (name="modification", columnDefinition="TEXT")
private String modification;
#Column (name="delivery", columnDefinition = "BIT", length = 1)
private Boolean delivery=true;
#OneToMany(mappedBy="order3d", cascade=CascadeType.ALL)
private Set<DrawFile> myDraws=new HashSet<DrawFile>(5);
public void addDrawFile(DrawFile df) {
df.setOrder3d(this);
myDraws.add(df);
}
}
#Entity
#Table (name="draw")
public class DrawFile implements Serializable {
private static final long serialVersionUID = -9024754876558087847L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name="id")
private int id;
#Column (name="hashname", columnDefinition="CHAR(64)")
private String hashname;
#Column (name="filename")
private String filename="";
#Column (name="accepted", columnDefinition = "BIT", length = 1)
private Boolean accepted=true;
#Column (name="format")
private String format;
#Column (name="size")
private int size;
#Column(name="width")
short width;
#Column(name="depth")
short depth;
#Column(name="height")
short height;
#OneToMany(mappedBy="draw", cascade=CascadeType.ALL)
private Set<Order3dLine> myLines=new HashSet<Order3dLine>(5);
#ManyToOne
#JoinColumn(name="order3d_id")
private Order3d order3d;
public void addLine(Order3dLine l) {
l.setDraw(this);
myLines.add(l);
}
}
#Entity
#Table (name="line3d")
public class Order3dLine implements Serializable {
private static final long serialVersionUID = 3993578603382571145L;
#NaturalId
#ManyToOne
#JoinColumn(name="draw_id")
private DrawFile draw;
#Column (name="quantity")
private short quantity=0;
#Id
#Column (name="material")
private String material;
#Id
#Column (name="color")
private int color;
#Column(name="produced")
short produced=0;
#Column(name="duration")
short duration=0;
}
Here are my MySQL tables:
CREATE TABLE `draw` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`filename` varchar(255) DEFAULT NULL,
`format` varchar(6) DEFAULT NULL,
`hashname` char(64) DEFAULT NULL,
`accepted` bit(1) NOT NULL DEFAULT b'0',
`size` int(11) NOT NULL DEFAULT '0',
`order3d_id` int(11) NOT NULL,
`width` smallint(6) NOT NULL DEFAULT '0',
`depth` smallint(6) NOT NULL DEFAULT '0',
`height` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT `fk_draw_order3d` FOREIGN KEY (`id`) REFERENCES `order3d` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf-8;
/*!40101 SET character_set_client = #saved_cs_client */;
CREATE TABLE `line3d` (
`draw_id` int(11) NOT NULL,
`material` varchar(10) NOT NULL,
`color` int(11) NOT NULL,
`quantity` smallint(6) NOT NULL DEFAULT '0',
`produced` smallint(6) NOT NULL DEFAULT '0',
`duration` smallint(6) NOT NULL DEFAULT '0',
`layers` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`draw_id`,`material`,`color`),
CONSTRAINT `fk_line_draw` FOREIGN KEY (`draw_id`) REFERENCES `draw` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf-8;
CREATE TABLE `order3d` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person` int(11) DEFAULT NULL,
`state` smallint(6) DEFAULT NULL,
`labor_expense` float DEFAULT NULL,
`travel_expense` float DEFAULT NULL,
`validity_date` date DEFAULT NULL,
`estimate_date` date DEFAULT NULL,
`order_date` date DEFAULT NULL,
`delivery` bit(1) NOT NULL DEFAULT b'0',
`modification` text,
`demand_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_order_user` (`person`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`person`) REFERENCES `person` (`id`) ON DELETE SET NULL ON UPDATE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf-8;
(1) You have a bi-directional relation between order and order line.
Hibernate expects you to assign order to line like in this convenience method:
#Entity
#Table(name="ORDERS")
public class Order {
[...]
public void addLine(OrderLine line) {
line.setOrder(this);
myLines.add(line);
}
}
See also this thread.
(2) "order" is not accepted as an valid table table name. Choose for example "orders".
(3) You forgot the cascade option on your one-to-one relation between order line and draw. Consider using #Embedded instead of #OneToOne. See Hibernate Doc
I put together minimal working example:
Order:
#Entity
#Table(name = "ORDERS")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "id")
private Long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name="line_id", nullable = false)
private Set<OrderLine> lines = new HashSet<OrderLine>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<OrderLine> getLines() {
return lines;
}
public void setLines(Set<OrderLine> lines) {
this.lines = lines;
}
public void addLine(OrderLine line) {
line.setOrder(this);
lines.add(line);
}
}
Order line:
#Entity
#Table(name = "ORDER_LINES")
public class OrderLine {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "id")
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
private Order order;
#Column(name = "content")
private String content;
#Embedded
private OrderDraw draw;
public OrderDraw getDraw() {
return draw;
}
public void setDraw(OrderDraw draw) {
this.draw = draw;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
Order Draw (whatever this is)
#Embeddable
public class OrderDraw {
private int width;
private int height;
public OrderDraw() {
this(0,0);
}
public OrderDraw(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}

Hibernate transitive composite foreign key dependency with embedded entity

I want to map a existing database (we can't change for now) to Hibernate entities.
But my mapping seems to have a problem with a transitive mapped composite keys I can't overcome.
FluidSampleLabel has FluidSample as foreign key and as part of its own composite primary key. Hibernate seems to ignore the columns/embedded id mapped by the embedded foreign key entity FluidSample in FluidSampleLabel.
Test-Project on Github:
https://github.com/burka/hibernate-transitive-compkey-problem.git
org.hibernate.AnnotationException: A Foreign key refering compkey_problem.model.FluidSample from compkey_problem.model.FluidSampleLabel has the wrong number of column. should be 1
Without #ManyToOne annotated named columns on embedded fks I get the following error:
Caused by: org.hibernate.MappingException: Foreign key (FK246FD874D0837E3B:fluid_sample_label [sample])) must have same number of columns as the referenced primary key (fluid_sample [sampleGroup,pre_post])
create sequence sample_group_seq start 10000;
create table sample_group (
sample_group_id int primary key,
payload varchar(200)
);
create table fluid_sample (
sample_group_id int not null,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
amount number(20,10) not null,
primary key ( sample_group_id, pre_post ),
constraint fk_fluid_sample_group foreign key ( sample_group_id ) references sample_group ( sample_group_id )
);
create table fluid_sample_label (
sample_group_id int,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
label varchar(200) not null,
primary key ( sample_group_id, pre_post, label ),
constraint fk_fluid_label_fluid foreign key ( sample_group_id, pre_post ) references fluid_sample ( sample_group_id, pre_post )
);
#Entity
#SequenceGenerator(name = "sampleGroupSequence", sequenceName = "sample_group_seq", allocationSize = 1)
#Table(name = "sample_group")
public class SampleGroup
{
#Id
#GeneratedValue(generator = "sampleGroupSequence", strategy = GenerationType.SEQUENCE)
#Column(name = "sample_group_id")
private Integer sampleGroupId;
#OneToMany(mappedBy = "sampleGroup")
private List<FluidSample> fluidSamples = new ArrayList<>();
#Column(name = "payload")
private String payload;
public SampleGroup()
{
}
public FluidSample addNewPreFluidSample()
{
FluidSample sample = new FluidSample(this, PrePost.PRE);
this.fluidSamples.add(sample);
return sample;
}
}
#Entity
#Table(name = "fluid_sample")
public class FluidSample
{
#Id
#ManyToOne
#JoinColumn(name = "sample_group_id")
private SampleGroup sampleGroup;
#Id
#Column(name = "pre_post")
#Enumerated(EnumType.STRING)
private PrePost prePost;
#OneToMany(mappedBy = "sample")
private List<FluidSampleLabel> labels = new ArrayList<>();
#Column(name = "amount")
private BigDecimal amount;
#SuppressWarnings("unused")
private FluidSample()
{
}
public FluidSample(SampleGroup sampleGroup, PrePost prePost)
{
this.sampleGroup = sampleGroup;
this.prePost = prePost;
}
public FluidSampleLabel addNewLabel(String value)
{
FluidSampleLabel label = new FluidSampleLabel(this, value);
this.labels.add(label);
return label;
}
}
#Entity
#Table(name = "fluid_sample_label")
public class FluidSampleLabel
{
#Id
#ManyToOne
#JoinColumns({ #JoinColumn(name = "sample_group_id"), #JoinColumn(name = "pre_post")})
private FluidSample sample;
#Id
private String value;
#SuppressWarnings("unused")
private FluidSampleLabel()
{
}
FluidSampleLabel(FluidSample sample, String value)
{
this.sample = sample;
this.value = value;
}
public String getValue()
{
return this.value;
}
}
public enum PrePost
{
PRE, POST;
}

JPA Hibernate - Mapping MySQL Composite keys to JPA (Hibernate) entities

I am trying to map the following table
CREATE TABLE Person (
p_id varchar(255) not null,
p_name varchar(255 not null,
p_post_code varchar(12) not null,
primary key (p_id, p_name),
);
Usually when i map an Entity to the above table i would do something like this (for single column primary keys):
private int p_id;
private String p_name;
private String p_post_code;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="p_id")
public Long getPId() {
return p_id;
}
public void setPId(int p_id) {
this.p_id = p_id;
}
#Column(name="p_name")
public String getPname() {
return p_name;
}
public void setPname(String string) {
this.p_name = string;
}
#Column(name="p_post_code")
public String getPostCode() {
return p_post_code;
}
public void setPostCode(String string) {
this.p_post_code = string;
}
The above works if the primary key is a single column (i.e. p_id) and the value for this column is generated in the database.
How would i modify the above to map it so that both p_id and p_name are the primary key.
Also, how would this work, if the composite key is a foreign key in another table.
I am trying to google for some examples but i cant find a simple example and most seem to be using the XML based configuration.
When using composite keys with JPA you need to use an embedded class as an id.
In your case you would have a person class and a primary key class for person:
#entity
public class Person
{
#EmbeddedId
private PersonPK key;
#Column(name="p_post_code", nullable = false)
private String p_post_code;
//....
}
#Embeddable
public class PersonPK
{
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="p_id");
private Long p_id;
#Column(name="p_name")
private String p_name;
public PersonPK(String name)
{
p_name = name;
}
//....
}
Using a class for the person's name (so the name is also a foreign key):
#entity
public class Person
{
#EmbeddedId
private PersonPK key;
#MapsId(value="p_name_id")
#ManyToOne
#JoinColumn(name = "p_name_id", referencedColumnName = "id")
private Name p_name;
#Column(name="p_post_code", nullable = false)
private String p_post_code;
//....
}
#Embeddable
public class PersonPK
{
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="p_id");
private Long p_id;
#Column(name="p_name_id")
private Long p_name_id;
public PersonPK(Name name)
{
p_name_id = name.getId();
}
//....
}
#Entity
public class Name
{
#Id
#GeneratedValue(some generation strategy here)
#Column(name="id")
private Long id;
#Column(name="name")
private String name;
//....
}

Categories

Resources