Spring JPA Multiple Many-To-One Relationships in One Entity - java

I'm trying to create an entity, User who has two Addresses, a home address and a work address.
Instead of storing the address info directly in the User class, I want to normalize it and store all addresses in one table and then link them to the user. Like so:
#Entity
public class User {
#Id
private Integer id;
private Address homeAddress;
private Address workAddress;
// getters and setters
}
#Entity
public class Address {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Integer id;
private String streetNumberAndName;
private String apartmentOrSuiteNumber;
private String city;
private String state;
private String zipcode;
// getters and setters
}
How do I do this using Spring JPA? I understand this is a ManyToOne relationship but I'm not sure how to map two ManyToOne relationships to one entity. Is this even possible?
Any help much appreciated.
Thanks!

That's really simple. Just map your User class like:
#Entity
public class User {
#Id
private Integer id;
#ManyToOne
#JoinColumn(name = "fk_home_address")
private Address homeAddress;
#ManyToOne
#JoinColumn(name = "fk_work_address")
private Address workAddress;
// getters and setters
}
The table structure would be like this:
user(id, fk_home_address, fk_work_address)
Note that this is a unidirectional relationship.
The best place to look for examples if you want to learn more is here.
If you're looking for a bidirectional relation, learn here.

private Integer id;
private Address homeAddress;
private Address workAddress;
with first situation, your structure table will be
user(id,home_address_id,work_address_id)
You might consider about second structure
private Integer id;
private List<Address> userddress;//using one to many
your table structure will be
address(id,user_id)
It depend how do you want to organize the structure.

Related

How can I include references in spring rest response?

I have defined two JPARepository with spring: "Person" and "Address". I also specified a relation between Person and Address.
I can fetch all persons with:
http://localhost:8080/person/
and all address with: http://localhost:8080/address/
Also I can get the address of a single person with http://localhost:8080/person/1/address
Now I'd like to get the address to every person as a nested address when I get request: http://localhost:8080/person/
How can I include the relations in the response?
My classes as requested by #nicolasl
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
#OneToOne
#JoinColumn(name = "address_id")
private Address address;
//Getter/Setter here
}
#Entity
public class Address {
#Id
#GeneratedValue
private long id;
#Column(nullable = false)
private String location;
#OneToOne(mappedBy = "address")
private Person person;
//Getter/Setter here
}
Well, I guess you just can't, not using the automated rest engine provided by spring. The rest API will return links to retrieve the related entities in the "_links" section of your JSON response (you can read more about that in http://stateless.co/hal_specification.html). You'd have to call those links to retrieve your Addresses.
Another way to solve this, is implementing your own repository and assembling your own JSON response.

Hibernate Mapping Only one class

Hibernate Mapping
How to implement such a code?
Each company has two properties, they are company name and estimated annual earnings.
There are two types of companies: 1- Main company, 2 - Subsidiary company.
The company can belong only to one company but can have a few child companies.
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String companyName;
private double estimatedAnnualEarnings;
private Company company; // here need to do a #OneToOne
private List<Company> subsidiaryCompany; // here need to do a #OneToMany
}
In your Implementation you should use :
The #Entity annotation in your class level, so the entity can be persisted to database.
The #Column annotation with the companyName and estimatedAnnualEarnings properties, so they can be persisted as columns in the database.
#ManyToOne annotation with the company field, so it can be mapped with a self-reference relationship.
The same goes with the subsidiaryCompany List which needs to be mapped with #OneToMany annotation to have a relationship too.
This is how should be your code:
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String companyName;
#Column
private double estimatedAnnualEarnings;
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name="mainCompanyId")
private Company mainCompany;
#OneToMany(mappedBy="mainCompany")
private List<Company> subsidiaryCompanies;
//getters and setters goes here
}
Note
I changed the name of company field to mainCompany and
subsidiaryCompaniy to subsidiaryCompanies for better readability
and to make it fit the logic better.
If you want to give your entity a different name in the database you
should use #Table(name="differentName") in the class level with
#Entity annotation, the smae thing with the columns you can add
name property to the #Column annotation i.e
#Column(name="company_name") if you want different names.

JPA Hibernate :: Inheritance of an entity, with additional OneToMany Lists

I'm using JPA Hibernate/Spring boot to build a web server with MySQL database, and I'm trying to extend a POJO Entity that looks like this, with additional OneToMany Lists.
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private String name;
....Constructors, getters and setters....
}
with this basic user entity, I just wanna make a UserInfo entity with additional information about the user's careers.
#Entity
public class UserInfo extends User {
#OneToMany(cascade= CascadeType.ALL, fetch= FetchType.EAGER)
#JoinColumn(name="user_id", referencedColumnName = "id")
private List<Career> careers;
....Constructors, getters, setters......
}
And I'm quite confused which inheritance strategy I should choose. I don't think its necessary to make another column or table for this.
Or should I just query twice..?
I'm kinda new to JPA so not sure which is considered as the best practice or design..
Edit:
This is how Career entity looks like. Just in case..
#Entity
#Table(name="career")
public class Career {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private Integer user_id;
#Column(nullable=false)
private String name;
#Column(nullable=false)
private String description;
....Constructors, getters and setters....
}
Since extending User table was meaningless(just in my case), I changed the User class like this.
#Table(name="user")
public class User {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private String name;
#OneToMany(fetch= FetchType.LAZY)
#JoinColumn(name="user_id", referencedColumnName = "id")
private List<Career> careers;
....Constructors, getters, setters......
}
Now I'm trying this with Spring Data JPA, and when I try to show the list of Users with their Careers, it is now querying more than 40 times taking about a minute to show the result.
Is this the N+1 problem..? how can I solve this?
In my opinion the error lies within the model itself. Why should UserInfo extend User? I cannot imagine which attributes or methods the UserInfo should inherit from a User. Typical inheritances would be "Developer" or "Administrator".
Why don't you add UserInfo as a 1:1 relation in your User entity? Another option is to omit UserInfo and put the Careers as a 1:n relation right into your User.
To prevent possible n+1 issues on a growing number of Careers you might want to change the fetch mode. See below
#OneToMany(fetch=FetchType.LAZY,mappedBy="user")
#Fetch(FetchMode.SUBSELECT)
private Set<Career> careers = new HashSet<>();

jpa inheritance - reuse an entity in several others

I am new to jpa and wonder how I have to realize this. I want to use an Entity called Address in several other Entities.
Car entity:
#Entity
public class Car
#Id
private String id;
private String licensePlate;
#ManyToOne
private Address address;
public Car() {
}
/* Getter and setters */
....
..
Person entity:
#Entity
public class Person {
#Id
private String id;
private String name;
#OneToMany(mappedBy = "address", cascade = CascadeType.ALL)
private Set<Address> addresses;
public Person() {
}
/* Getter and setters */
....
..
Address entity:
#Entity
public class Address {
#Id
private String id
private String streetAndNumber;
/* Now what?????? */
private Car car; // would fit for car
private Person person; // would fit for person
// But what would be fitted both?
I searched the internet to find a solution. But, most likely to my lack of knowledge. I couldn't find something understandable.
There is actually no need to make all relations bidirectional, it's a best practice to prefer unidirectional relationships in a model whenever possible, see Domain Driven Design Quickly.
In this case Address does not need to know of all the entities that it's associated with. Also consider making the address a Value Object (see DDD quickly) using the #Embeddable annotation.

How to store some of the entity's values in another table using hibernate?

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

Categories

Resources