How to implement relationship between 2 classes using ORMLite? I know about foreign field, but i can't add non-string Department field to product class
Class Product
#DatabaseTable(tableName = "PRODUCTS")
public class Product {
#DatabaseField(id = true)
private String id;
#DatabaseField()
private String name;
#DatabaseField() //This field is id of Department class
private String department;
Department class
#DatabaseTable(tableName = "DEPARTMENTS")
public class Department {
#DatabaseField(id = true)
private String id;
#DatabaseField()
private String name;
How to implement relationship between 2 classes using ORMLite? I know about foreign field, but i can't add non-string Department field to product class
RTFM please. Did you look at any of the documentation or examples? Here's the docs on foreign objects. You can see plainly that you put a Department into Product not a String. The docs show the Order object having an Account field.
#DatabaseField
private Department department;
Behind the scenes, what ORMLite does is actually store just the id from the department into your Product. If you actually look at the schema then you will see a string there but you don't do that yourself.
Then when you retrieve your Product, it will have a Department field but only the id will be filled out.
There is also a foreign object example in the code that may also help.
Related
I am trying to insert a list of entities which have one to one relation to another entity. It is possible that the one to one mapped object would be same for many parent entity. I am expecting that the same child entity is referred in foreign keys of parent, but actually duplicate rows are getting created. Here are my Entities.
#Builder
#Entity
public class PaymentInfoType1 {
#Id
Long id;
LocalDate date;
#Column(precision = 15, scale = 2)
BigDecimal amount;
String reference;
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "account", referencedColumnName = "id")
Account account;
}
#Builder
#Entity
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Account {
#Id
Long id;
#EqualsAndHashCode.Include
String name;
#EqualsAndHashCode.Include
String accountId;
}
I am creating a list of PaymentInfoType1 based on the information received from a different system. Each PaymentInfoType1 get created along with its Account, which could have exactly the same info but different objects in realtime.
When i do:
PaymentInfoType1 first = // Created with some logic
Account account1 = // name = sample & accountId = 123
first.setAccount(account1);
PaymentInfoType1 second = // Created with some logic
Account account2 = // name = sample & accountId = 123
second.setAccount(account2);
// Both the above its own account object but the field have exactly same values.
List<PaymentInfoType1> list = List.of(first, second);
repo.saveAll(list);
I was expecting that there will be two rows in PaymentInfoType1 table and one in Account, but found that Account also has two rows. Looks like Equals and HashCode does not have any effect in this case.
How can handle this to not insert duplicate rows when the mapping objects are similar by equals/hashcode.
JPA does nothing with #EqualsAndHashcode (that just generates class methods equals and hashCode).
JPA identifies entities by entity id annotated with #Id (or #EmebeddedId) and this id is also something that can be implemented and checked - and usually also generated (like some db sequence) - in the database level.
If you want to use Account identified by name and accountId on JPA side you need to use #EmbeddedId and #Embeddable and get rid of #Id. This would be something like:
#Embeddable
public class AccountId {
String name;
String accountId; // maybe needs renaming...
}
and then in the Account:
#EmbeddedId
AccountId accountId;
See this for example
I am studying for the Spring Core certification and I have some doubts about how works the Embeddables JPA class.
So I have this example:
1) A Customer entity class that map the T_CUSTOMER DB table
#Entity
#Table(name= “T_CUSTOMER”)
public class Customer {
#Id
#Column (name=“cust_id”)
private Long id;
#Embedded
#AttributeOverride
(name="postcode", column=#Column(name="ZIP"))
private Address office;
…
…
…
}
2) An Address entity class that simply represent an address (and that not map any DB table):
#Embeddable
public class Address {
private String street;
private String suburb;
private String city;
private String postcode;
private String country;
}
As you can see in the Customer entity class there is this field:
#Embedded
#AttributeOverride
(name="postcode", column=#Column(name="ZIP"))
private Address office;
What exactly are the rules and the meaning of the #Embedded and #AttributeOverride annotations?
I think that this works in the following way:
1) Some column of the T_CUSTOMER DB table are mapped not directly into the Customer entity class but are mapped and stored into the field of the Address class that is a field of the the Customer class.
2) The table column named ZIP is mapped with the postcode property of the Address class.
Is it right or am I missing something?
Tnx
I am using Hibernate and have two tables, STUDENTS and DORM_ROOMS, that are related with a composite key:
STUDENTS table:
CAMPUS(String) Part of Composite Key
STUDENT_ID (int) Part of Composite Key
NAME (String)
...
DORM_ROOMS table:
CAMPUS(String) Part of Composite Key
STUDENT_ID (int) Part of Composite Key
ROOM_NUMBER(int)
...
The relationship is one to one because a student can be associated with exactly one dorm room and and a dorm room is associated with one student (wow - a private room!). However, not all students have a dorm room.
My initial code (stripped down) looks like:
FOR STUDENTS:
#Embeddable
public class StudentsPK implements Serializable {
#Column(name = "CAMPUS")
private String Campus;
#Column(name = "STUDENT_ID")
private String StudentID;
...
}
#Entity
#Table(name = "STUDENTS")
public class Students implements Serializable {
#EmbeddedId
private StudentsPK studentsPK;
...
}
FOR DORM_ROOMS:
#Embeddable
public class DormRoomsPK implements Serializable {
#Column(name = "CAMPUS")
private String Campus;
#Column(name = "STUDENT_ID")
private String StudentID;
...
}
#Entity
#Table(name = "DORM_ROOMS")
public class DormRooms implements Serializable {
#EmbeddedId
private DormRoomsPK dormRoomsPK;
...
}
Assume that the database schema is already defined and created. In particular, CAMPUS+STUDENT_ID is a PK for STUDENTS and CAMPUS+STUDENT_ID is a FK for DORM_ROOMS that serves as the PK in that table. At this point I can successfully insert a row into STUDENTS and a row into DORM_ROOMS. I can also retrieve any student from STUDENTS even if the student does not have a dorm room. However, I have not yet "informed" Hibernate about the relationship between the two tables. That is where I am confused.
I tried to "relate" the two tables by using a "JOIN" annotation but I discovered that this causes any attempt to fetch a student that has no dorm room to return an empty result set. I suppose that makes since if "JOIN" states that the tables are to always be viewed as joined then joining a student having no dorm room with no matching rows in the DORM_ROOMS table would result in an empty result set.
Since using a "JOIN" annotation doesn't work, how do I modify my code to describe the relationship between the two tables but still allow me to fetch students that have no matching dorm rooms?
Thank you.
It sounds like you are looking for the #OneToOne annotation, which also has the ability to specify if the relationship is optional. There are some examples described in the JBoss JPA 2.1 docs, here is one of them.
Example 3: One-to-one association from an embeddable class to another entity.
#Entity
public class Employee {
#Id int id;
#Embedded LocationDetails location;
...
}
#Embeddable
public class LocationDetails {
int officeNumber;
#OneToOne ParkingSpot parkingSpot;
...
}
#Entity
public class ParkingSpot {
#Id int id;
String garage;
#OneToOne(mappedBy="location.parkingSpot") Employee assignedTo;
}
Found the problem! I discovered that in a #OneToOne relationship with a composite key, using a separate FK class to manage the composite key in both entities causes the error. The problem is shown in my original posting where I define and use StudentsPK and DormRoomsPK! Once I changed to use a single "PK" class instead of these two my problem was eliminated. (This doesn't appear to be a well documented requirement!)
I'm currently trying to create a pair of Hibernate annotated classes to load (read only) from a pair of tables in a legacy system. The legacy system uses a consistent (if somewhat dated) approach to keying tables. The tables I'm attempting to map are as follows:
Customer CustomerAddress
-------------------------- ----------------------------
customerNumber:string (pk) customerNumber:string (pk_1)
name:string sequenceNumber:int (pk_2)
street:string
postalCode:string
I've approached this by creating a CustomerAddress class like this:
#Entity
#Table(name="CustomerAddress")
#IdClass(CustomerAddressKey.class)
public class CustomerAddress {
#Id
#AttributeOverrides({
#AttributeOverride(name = "customerNumber", column = #Column(name="customerNumber")),
#AttributeOverride(name = "sequenceNumber", column = #Column(name="sequenceNumber"))
})
private String customerNumber;
private int sequenceNumber;
private String name;
private String postalCode;
...
}
Where the CustomerAddressKey class is a simple Serializable object with the two key fields. The Customer object is then defined as:
#Entity
#Table(name = "Customer")
public class Customer {
private String customerNumber;
private List<CustomerAddress> addresses = new ArrayList<CustomerAddress>();
private String name;
...
}
So, my question is: how do I express the OneToMany relationship on the Customer table?
I may have an answer for my own question. Add the following to Customer:
#OneToMany(mappedBy="customer")
#JoinColumn(name="customerNumber")
List<CustomerAddress> addresses = new ArrayList<CustomerAddress>();
And the following to CustomerAddress:
#ManyToOne
#JoinColumn(name="customerNumber")
protected Customer customer;
This turns out to be a simpler problem to solve than I first thought. Typical.
I assume you have read the Bauer/King Hibernate book, which is extremely bad at explaining how do implement composite primary keys correctly. Don't let yourself be fooled by a bad book: composite primary key are not a property of legacy systems...
is there a simple way to persist some of the fields in another class and table using hibernate.
For example, I have a Person class with name, surname, email, address1, address2, city, country fields. I want my classes to be:
public class Person
{
private String name;
private String surname;
private String email;
private Address address;
// ..
}
public class Address
{
private Person person; // to whom this belongs
private String address1;
private String address2;
private String city;
private String country;
// ..
}
and I want to store Address in another table. What is the best way to achieve this?
Edit: I am using annotations. It does not have to be the way I described, I am looking for best practices.
Edit 2: What will be the Id of Address?
PS. If there is a way to make Address immutable (to use as a value object) that is even better, or maybe not because I thought everything from wrong perspective :)
map Address as an entity and add a primary key (an auto-generated id)
map the relation between Person and Address as one-to-one (#OneToOne on each field)
With Hibernate 3.5 it is possible to define foreign generators (aka. JPA mapping), details are here.
It is pretty straight forward Person should implement Serializable then #Id annotation is added to person.
#Entity
#AccessType(value = "field")
#Table(name = "addresses")
public class Address
{
#Id
#OneToOne
#JoinColumn(name = "person_id")
private Person person;
// ...
}
There is an alternative but I really like the first one:
#Entity
#AccessType(value = "field")
#Table(name = "addresses")
public class Address
{
#Id
private int personId;
#MapsId
#OneToOne
#JoinColumn(name = "person_id")
private Person person;
// ...
}