How to model compound key in Hibernate? - java

I am modeling a model class in java with Hibernate. But the table in the DB already exists and I want to use it.
The problem is that the table do not have an ID. Besides, the worse is that the tuple in the table are formed by four columns and their combination makes a "kind of identification/ID". Also, the columns are not FK to others tables.
Is there a way to model this with java, hibernate, and so on, without "fix/alter" the table?
Thanks

You have to define your class with an #EmbeddedId Example:
Your Entity that already exists :
#Entity
#Table(name = "ENTITY_EXAMPLE")
public class EntityExample {
// this is your new class Embeddable
#EmbeddedId
private EntityExampleId id;
//other fields
//geters y seters
//////////////////////////
}
And have to create other Class #Embeddable that contains your 4 columns of your composite ID
#Embeddable
public class EntityExampleId implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "COLUMN1", nullable = false)
private Integer col1;
#Column(name = "COLUMN2", nullable = false)
private Integer col2;
#Column(name = "COLUMN3", nullable = false)
private Date col3;
#Column(name = "COLUMN4", nullable = false)
private Date col4;
//geters y seters
//////////////////////////
}
For more info see the references
reference 1
reference 2
reference 3

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;
}

Use a generic data object (and table) for several #OneToOne mappings

Instead of having several small objects (which have mostly the same properties like ID and NAME) mapped as #OneToOne, I would like to have one "generic" kind of object which is mapped to a single database table, and should be referenced by a kind of discriminator column group_id in this case.
The code examples should make it clear what I want to achieve:
#Entity
#Table(name = "GENERAL_DATA")
public class GeneralData {
#Id
#Column(name = "GROUP_ID")
private int groupId;
#Id
#Column(name = "ID")
private int id;
#Column(name = "NAME")
private String name;
}
#Entity
#Table(name = "INVOICE")
public class Invoice {
#OneToOne
#JoinColumn(name = "STATUS")
private GeneralData status;
#OneToOne
#JoinColumn(name = "COLOR")
private GeneralData color;
}
The database table structure of GeneralData should be like this:
group_id id name
-----------------------------
1 1 Active
1 2 Processing
1 3 Cancelled
2 1 Blue
2 2 Green
2 3 Red
Why won't you get rid of GeneralData entity and use simple enums in invoice entity? If you have specified Statuses / Colors it is better way.
#Entity
#Table(name = "INVOICE")
public class Invoice {
#Column(name = "STATUS")
private Status status;
#Column(name = "COLOR")
private Color color;
}
public enum Status {
ACTIVE,
PROCESSING,
CANCELLED
}
// ...

Many to one Hibernate mapping

So, here'e the situation:
Table ComputerInventory with {computerInventoryID (Primary key), TagID(unique), Name etc}
Table reviewStatus with {reviewStatusID(Primary key), computerInventoryID (ForeignKey), status }
I've written the hibernate Entity for ReviewStatus:
public class ReviewStatus implements Serializable {
public enum reviewStatus {
To_Be_Reviewed,
Reviewed
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long reviewStatusId;
#Column(name = "lastModifiedTime")
private Date lastModifiedTime;
#Column(name = "Comments")
private String comments;
#Enumerated(EnumType.STRING)
#Column(name = "status")
//all above params have gettetrs and setters
private reviewStatus status;
//TODO: Mapping to computerinventory
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "computerInventoryId")
//For one ComputerInventoryID, there can be many review Statuses.
private Set<ReviewStatus> reviewStatusSet;
public long getreviewStatusId() {
return reviewStatusId;
}
My Doubts:
For one ComputerInventoryID, there can be many review Statuses, so do I have a
Set<ReviewStatus> reviewStatusSet
where I return the list of entries in reviewstatus? Sorry, but I don't understand how I can write a get/set for returning and setting the reviews status of a bunch of records.
Your reference from ReviewStatus should be to a ComputerInventory, not to its ID. Hibernate lets you abstract out the details of the primary key (the ID), letting you directly reference from one object to another. You should use an #ManyToOne annotation on your private ComputerInventory computerInventory;.

Hibernate / JPA returns list of nulls

I have an entity like this:
#Entity
#Table(name = "MY_TABLE")
public class OrderPackage implements Serializable {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "pId", column = #Column(name = "P_ID")),
#AttributeOverride(name = "prId", column = #Column(name = "PR_ID")),
#AttributeOverride(name = "pin", column = #Column(name = "PIN")),
#AttributeOverride(name = "Id", column = #Column(name = "MN_ID"))
})
private PackageId id;
#Column(name = "MEM_ID")
private Long memberId;
.....
.....
// more fields and getters and setters
}
PackageId.class
#Embeddable
public class PackageId implements Serializable {
private String pId;
private String prId;
private String pin;
private Long Id;
// getters and setters
}
Mytable has the following fields matching for my query:
SELECT c FROM OrderPackage c where <condition> order by c.prId;
Matching records like this:
MN_ID MEM_ID P_ID PR_ID PIN ///some other fields
6217 402022795 A1000005361 B1000077615 (null)
6213 402022795 A1000005361 B1000037615 (null)
6218 402022795 A1000005361 B1000087615 (null)
6215 402022795 A1000005361 B1000057615 (null)
MN_ID is unique here.
I get the count 4. But all null rows in the list.
What could be causing this?
jBoss 4.2.x
JPA
Hibernate
ORACLE
UPDATE:
Is this still the case? (When there a null value for any one of the fields in the Composite Key, then it returns null for that entire row)
http://thelittlefellow.blogspot.com/2011/07/hibernate-gethibernatetemplatefind.html
https://hibernate.atlassian.net/browse/HHH-177

Categories