Composite keys with Hibernate - java

I need help to create the correct pojo's from this database...
https://www.dropbox.com/s/j2lfu44zpqfcxb4/dbr.PNG
I have tried creating this classes...
#Entity
#Table(name="Municipio", catalog="elecciones2014", schema="")
public class Municipio implements Serializable{
#EmbeddedId
private MunicipioPk idMunicipio;
#Basic(optional=false)
#Column(name="nomb_municipio")
private String nomb_municipio;
}
With this Embedded class
#Embeddable
class MunicipioPk implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Column(name="id_depto")
String departamento;
#Column(name="id_municipio")
String idMunicipio;
}
The problem is when i want to reference to 'Municipio' from 'JRV' y don't know how to access to field 'id_municipio'. I had this code but it doesn't work
#Entity
#Table(name = "JRV", catalog = "elecciones2014", schema = "")
public class Jrv {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_jrv")
private int id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="id_municipio",referencedColumnName="idMunicipio")
private Municipio municipio;
#ManyToOne
#JoinColumn(name="DUI",referencedColumnName="dui")
private PadronElectoral dui;
}
can someone help me?
how I have to do it?
Thanks in advice!!

Here you are defining single join column, but the Municipio entity's PK has two columns. Also the referencedColumnName should be the name of the column not the entity's property.
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="id_municipio",referencedColumnName="idMunicipio")
private Municipio municipio;
So you could do something like this:
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="id_municipio", referencedColumnName="id_municipio"),
#JoinColumn(name="id_depto", referencedColumnName="id_depto")
})
private Municipio municipio;
Which translates to this SQL (I got this by generating SQL schema from your entities after the modification mentioned above):
create table elecciones2014.JRV (
id_jrv serial not null,
id_depto varchar(255),
id_municipio varchar(255),
primary key (id_jrv)
);
alter table elecciones2014.JRV
add constraint FK_7scd8alu3nf4tsyh3hq2ryrja
foreign key (id_depto, id_municipio)
references elecciones2014.Municipio;

Related

How to create Spring Entity and Repository without primary key

I have a table with two columns user_id and role_id. There's no unique column in table and I can't add one. How can I create Entity and Repository in Spring without a primary key?
This is my UserRole.class
public class UserRole {
#Column(name = "user_id")
private int userId;
#Column(name = "role_id")
private int roleId;
//getters and setters
}
But with this class i get the following error:
nested exception is org.hibernate.AnnotationException: No identifier specified for entity:
I saw that one of the answers is to use all of the columns as the id, but i have no idea how to do it.
Please see the awnser in this post. This should help you.
PK Explained
Another Option is if this is a join table, than you could make Embeded PK
#Embeddable
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(toBuilder = true)
public class PersonGroupPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#Column(insertable=false,unique = false, updatable=false, nullable=false)
private Long personId;
#Column(insertable=false, unique = false,updatable=false, nullable=false)
private Long groupId;
}

How to define the association table as pojo entity

I have 3 tables in the db. I am trying to write the JPA entities. I am facing some issues with Association table entity. My entities are as follows,
Person.java
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
//setter and getter
}
Exam.java
#Entity
#Table(name = "exam")
public class Exam {
#Id
#GeneratedValue
private long examId;
#Column(nullable = false)
private String examName;
#Column(nullable = false)
private int marks;
//Setters and getters
}
The table structure for association table is,
create table person_exam (
personId BIGINT not null,
examId BIGINT not null,
primary key (personId, examId)
);
I tried the association table entity with #ManyToMany annotation for both the properties which is not giving me the result.
Can anyone please suggest me what should I need to use (ManyToMany/OneToOne/ManyToOne/OneToMany ) in my entity for the above person_exam table.
from the PRO JPA 2nd Ed. book:
the only way to implement a many-to-many relationship is with a separate join table. The consequence of not having any join columns in either of the entity tables is that there is no way to determine which side is the owner of the relationship. Because every bidirectional relationship has to have both an owning side and an inverse side, we must pick one of the two entities to be the owner.
So I chose the the Person entity. Applying the needed changes to your incomplete code:
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
/**
* we need to add some additional metadata to the Person designated
* as the owner of the relationship, also you must fully specify the names of
* the join table and its columns because you already provided a schema
* for the association table, otherwise the JPA provider would generate one.
*/
#ManyToMany
#JoinTable(name="person_exam",
joinColumns=#JoinColumn(name="personId"),
inverseJoinColumns=#JoinColumn(name="examId"))
private Collection<Exams> exams;
//setter and getter
}
#Entity
#Table(name = "exam")
public class Exam {
#Id
#GeneratedValue
private long examId;
#Column(nullable = false)
private String examName;
#Column(nullable = false)
private int marks;
//Setters and getters
/**
* As in every other bidirectional relationship,
* the inverse side must use the mappedBy element to identify
* the owning attribute.
*/
#ManyToMany(mappedBy="exams")
private Collection<Person> people;
}

Map composite primary key to foreign key entities with Java Hibernate

I'm trying to retrieve a list of entities from a table with two primary keys which are ids to a foreign key each.
MySQL tables:
Paintings table:
id - int, PK, Auto increment
name - varchar(45)
Pictures table:
id - int, PK, Auto increment
name - varchar(45)
location - varchar(45)
painting_to_picture_link table:
painting_id - int, FK to id in painting
picture_id - int, FK to id in painting
I've set primary key (painting_id, picture_id)
and set them to their foreign keys also as written above.
In Java:
Painting.java
#Entity
#Table(name = "paintings")
public class Painting {
#Id
#GeneratedValue
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
...
}
Picture.java
#Entity
#Table(name = "pictures")
public class Pictures {
#Id
#GeneratedValue
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "location")
private String location;
...
}
PaintingPictureLink.class
public class PaintingPictureLink implements Serializable {
#<SOME ANNOTATION HERE>
private Painting painting;
#<SOME ANNOTATION HERE>
private Picture picture;
...
}
I've seen many examples, but didn't work for me.
I've tried putting #Id annotations, #EmbeddedId, etc... non worked.
The errors I get are that table isn't mapped, could not determine type for the models, missing #Id annotation... :|
Would appreciate help with querying this table and getting a list of PaintingPictureLink.
Some of the examples I've followed:
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Server/1.0/html/Hibernate_Annotations_Reference_Guide/ch03s02s06.html
Using an Entity (and their Primary Key) as another Entity's Id
Thanks,
Guy
Derp
Found the solution.
I created a primary key class:
#Embeddable
public class PicturePaintingPK implements Serializable {
#ManyToOne
private Painting painting;
#ManyToOne
private Picture picture;
public PicturePaintingPK() {}
// getters and setters //
}
In the PicturePaintingLink class:
#Entity
#Table(name = "painting_to_picture_link")
public class PaintingPictureLink implements Serializable {
#Id
private PicturePaintingPK primaryKey = new PicturePaintingPK()
...
//constructor//
...
public TTPK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(TTPK primaryKey) {
this.primaryKey = primaryKey;
}
// ... all the other getters and setters needed .... //
}
The source for this solution was from:
Example from Hibernate forum
Guy

Mapping extended entities with multiple ID's in Hibernate

I have implemented a db which is consisted of Article and Fruit tables, with the following specifications:
create table Fruit
(
ART_ID bigint,
FRU_ID bigint not null auto_increment,
FRU_FROZEN varchar(15),
primary key(FRU_ID)
);
# Implemented
create table Article
(
ART_ID bigint,
ART_NAME varchar(10) not null,
ART_COST varchar(10) not null,
primary key(ART_ID)
);
alter table Fruits add constraint FK_FRUIT_ARTICLE foreign key (ART_ID)
references Article (ART_ID) on delete restrict on update restrict;
and with following class entities :
Article.java
#Entity
#Table(name = "Article")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Article implements Serializable
{
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "ART_ID")
private Long id;
#Basic(optional = false)
#Column(name = "ART_NAME")
private String name;
#Basic(optional = true)
#Column(name = "ART_COST")
private String cost;
// constructors, getters and setters
Fruit.java
#Entity
#Table(name="Fruit")
public class Fruit extends Article{
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "FRU_ID")
private long fruitID;
#Basic(optional = false)
#Column(name = "FRU_FROZEN")
private String fruitFrozen;
// constructors, getters and setters
Now, my problem is how to have ID in Article and in Fruit, if I keep it this way, it throws me exception that sub-class must not contain IDClass because it will result with multiple ID's. Any help is appreciated. Thanks in advance.
It means what it says, an Entity cannot have two IDs.
Consider the operation
entityManager.find(Article.class, 1l);
How is it supposed to know which one to return if there are two articles (an article and a fruit) that both have id 1?
If your tables need to each have IDs, entity inheritance is not an appropriate solution. Consider putting the common elements in an #MappedSuperclass instead.

JPA #OneToOne with Shared ID -- Can I do this Better?

I’m working with an existing schema that I’d rather not change. The schema has a one-to-one relationship between tables Person and VitalStats, where Person has a primary key and VitalStats uses the same field as both its primary key and its foreign key to Person, meaning its value is the value of the corresponding PK of Person.
These records are created by external processes, and my JPA code never needs to update VitalStats.
For my object model I’d like my Person class to contain a VitalStats member, BUT:
When I try
#Entity
public class Person{
private long id;
#Id
public long getId(){ return id; }
private VitalStats vs;
#OneToOne(mappedBy = “person”)
public VitalStats getVs() { return vs; }
}
#Entity
public class VitalStats{
private Person person;
#OneToOne
public Person getPerson() { return person; }
}
I have the problem that VitalStats lacks an #Id, which doesn’t work for an #Entity.\
If I try
#Id #OneToOne
public Person getPerson() { return person; }
that solves the #Id problem but requires that Person be Serializable. We’ll get back to that.
I could make VitalStats #Embeddable and connect it to Person via an #ElementCollection, but then it would have to be accessed as a collection, even though I know that there’s only one element. Doable, but both a little bit annoying and a little bit confusing.
So what’s preventing me from just saying that Person implements Serializable? Nothing, really, except that I like everything in my code to be there for a reason, and I can’t see any logic to this, which makes my code less readable.
In the meantime I just replaced the Person field in VitalStats with a long personId and made that VitalStats’s #Id, so now the #OneToOne works.
All of these solutions to what seems (to me) like a straightforward issue are a bit clunky, so I’m wondering whether I’m missing anything, or whether someone can at least explain to me why Person has to be Serializable.
TIA
To map one-to-one association using shared primary keys use #PrimaryKeyJoinColumn and #MapsId annotation.
Relevant sections of the Hibernate Reference Documentation:
PrimaryKeyJoinColumn
The PrimaryKeyJoinColumn annotation does say that the primary key of
the entity is used as the foreign key value to the associated entity.
MapsId
The MapsId annotation ask Hibernate to copy the identifier from
another associated entity. In the Hibernate jargon, it is known as a
foreign generator but the JPA mapping reads better and is encouraged
Person.java
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "person_id")
private Long id;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private VitalStats vitalStats;
}
VitalStats.java
#Entity
public class VitalStats
{
#Id #Column(name="vitalstats_id") Long id;
#MapsId
#OneToOne(mappedBy = "vitalStats")
#JoinColumn(name = "vitalstats_id") //same name as id #Column
private Person person;
private String stats;
}
Person Database Table
CREATE TABLE person (
person_id bigint(20) NOT NULL auto_increment,
name varchar(255) default NULL,
PRIMARY KEY (`person_id`)
)
VitalStats Database Table
CREATE TABLE vitalstats
(
vitalstats_id bigint(20) NOT NULL,
stats varchar(255) default NULL,
PRIMARY KEY (`vitalstats_id`)
)
In my case this made the trick:
Parent class:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/** auto generated id (primary key) */
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private Long id;
/** user settings */
#OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
private Setting setting;
}
Child class:
public class Setting implements Serializable {
private static final long serialVersionUID = 1L;
/** setting id = user id */
#Id
#Column(unique = true, nullable = false)
private Long id;
/** user with this associated settings */
#MapsId
#OneToOne
#JoinColumn(name = "id")
private User user;
}

Categories