SpringBoot JPA persist child of parent with nulls columns - java

I have strange problem. I have entity Company, Branch and Address.
Company has list of branch and every branch has address.
Im trying to persist branch with not exist before address entity, but Address is persist with nulls columns.
#Data
#Entity
#Indexed
#Table(name = "company")
public class Company {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
private String id;
#Field
#Column(name = "full_name", nullable = false, unique = true)
private String fullName;
#OneToMany(mappedBy = "company")
private Set<Branch> branches;
}
#Data
#Entity
#Table(name = "branch")
public class Branch {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String phone;
#Column
private String email;
#OneToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#ManyToOne
#JoinColumn(name = "company_id", referencedColumnName = "id")
private Company company;
}
#Entity
#Table(name = "address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String street;
#OneToOne(mappedBy = "address")
private Company company;
#OneToOne(mappedBy = "address")
private Branch branch;
}
Service ...
public Integer addBranch(BranchDto branchDto) {
Branch branch = modelMapper.map(branchDto, Branch.class);
Company company = companyRepository.getCompanyById(branchDto.getCompanyId());
branch.setCompany(company);
return branchRepository.save(branch).getId();
}
Dto...
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class BranchDto {
private Integer id;
private String phone;
private String email;
private AddressDto address;
private String companyId;
}
And that is effect...
Debugger...
What is the problem? Can you help me ?

You are using 'mappedBy' with the same id, It only works with the first one he find.
Try to change to other id.

Related

Spring JPA how to create an object with relationship to another entity in Application

I want to create a Person with an Address, each of them are an entity. My Entities seem to work, the part where i begin to struggle is on how to create a Person using the constructor where i also have to put in the Address.
personRepository.save(new Person(new Name("Test","Test"),new Adress("Street","Number","PLZ","Town"),LocalDate.parse("2000-01-01"),"email#email.com","911");
This sadly does not work so my question is how can i create a Person object with the Address.
I'm also wondering how i would add the address if i already got the address in my Address repository, is there a way to get the address or use the adress ID?
adresseRepository.save(new Adresse("Street","Number","PLZ","Town"));
Here's the code for both of the shortend.
Person:
#Entity
#Table(name = "Person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "PersonID")
private Long personID;
#Column(name = "FullName")
#Convert(converter = NameConverter.class)
private Name fullName;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="AdresseID")
private Adresse adresse;
#Column(name = "Geburtsdatum")
private LocalDate geburtsdatum;
#Column(name = "EMail")
private String email;
#Column(name = "Telefonnummer")
private String telefonnummer;
private Person() {}
public Person(Name fullName, Adresse adresse, LocalDate geburtsdatum, String email, String telefonnummer) {
this.fullName = fullName;
this.adresse = adresse;
this.geburtsdatum = geburtsdatum;
this.email = email;
this.telefonnummer = telefonnummer;
}
}
Address:
#Entity
#Table(name = "Adresse")
public class Adresse {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "AdresseID")
private Long adresseID;
#Column(name = "Strasse")
private String strasse;
#Column(name = "Hausnummer")
private String hausnummer;
#Column(name = "PLZ")
private String plz;
#Column(name = "Ort")
private String ort;
protected Adresse() {}
public Adresse(String strasse, String hausnummer, String plz, String ort) {
this.strasse = strasse;
this.hausnummer = hausnummer;
this.plz = plz;
this.ort = ort;
}
}
Ralationships are created in hibernate like this:
#Entity
#Table(name="CART")
public class Cart {
//...
#OneToMany(mappedBy="cart")
private Set<Item> items;
// getters and setters
}
Please note that the #OneToMany annotation is used to define the property in Item class that will be used to map the mappedBy variable. That is why we have a property named “cart” in the Item class:
#Entity
#Table(name="ITEMS")
public class Item {
//...
#ManyToOne
#JoinColumn(name="cart_id", nullable=false)
private Cart cart;
public Item() {}
// getters and setters
}
Soin your case you just have to add
#Entity
#Table(name = "address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
//...
#OneToOne(mappedBy = "address")
private User user;
something lilke this to your Adress Table.
Because one Adress also have one user.
For more information visit this site

Address Entity in multiple Entities without specifying it

i am currently building an Application with Spring and i have a Question there:
I want to have an Entity Address which looks like this:
#Entity(name = "Address")
#Table(name = "address")
#EntityListeners(AuditingEntityListener.class)
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "city")
private String city;
#Column(name = "country")
private String country;
#Column(name = "postalcode")
private String postalCode;
#Column(name = "state")
private String state;
#Column(name = "street")
private String street;
public Address() {
}
}
I want to use this Address Entity in multiple Entities, for example in the User or Order Entity. Later, i will like to have many Entities which need an Address. But i don't want to specify each Relation in the Address Entity, otherwise it will get to complex. Is it possible to have a Link from the User to the Address with only specifying this Link in the User Entity?
My User Entity looks something like this:
#Entity(name = "User")
#Table(name = "User")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username")
private String userName;
#OneToOne(
mappedBy = "address",
orphanRemoval = true,
cascade = {
CascadeType.PERSIST,
CascadeType.REMOVE
}
)
private Address billingAddress;
public User() {
}
}
Yes, it is possible, but you don't actually need mappedBy property, otherwise you are telling JPA to search for a address property in the other side of the relationship (that you actually want to be unidirectional):
#Entity(name = "User")
#Table(name = "User")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username")
private String userName;
#OneToOne(
orphanRemoval = true,
cascade = { CascadeType.PERSIST, CascadeType.REMOVE }
)
private Address billingAddress;
public User() {
}
}
You can read more about this in the following online resources:
https://docs.oracle.com/javaee/6/api/javax/persistence/OneToOne.html
https://www.baeldung.com/jpa-one-to-one
https://javabydeveloper.com/one-one-unidirectional-association/

Thymeleaf to access data of joined tables

I have three tables that have one to one relation the first table is the province entity, the district entity which has a one to relation with the province and the person's entity as each person resides in on district.
I would like to access the district information in thymleaf.
#Entity
#Table (name = "provinces")
public class Province {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int provinceId;
#Column(name="province_name",unique=true,length = 25, nullable = false)
private String provinceName;
//getters and setters
}
#Entity
#Table (name = "districts")
public class District {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(unique=true,length = 25, nullable = false)
private String districtName;
#Column(unique=true, length = 10,nullable = false)
private String abbreviation;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="province")
private Province location;
}
#Entity
public class AppUser implements UserDetails {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private long id;
private String firstName;
private String lastName;
private String email;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "location_id")
private District location;
//getters and setters
}
service controller:
#GetMapping("/all")
private String viewDistricts (Model model){
model.addAttribute("listUsers",appUserService.listUser());
return "admin/users";
}
service:
public List<AppUser> listUser(){
return appUserRepository.findAll();
}
thymeleaf:
th:text="${users.location.districtName}"
org.springframework.expression.spel.SpelEvaluationException: EL1007E:
Property or field 'districtName' cannot be found on null
best practice to handle null pointer exception as follows
th:text="${users.location!=null}?${users.location.districtName}:''"
But, the root cause of the problem is that the associated object value is null.

#JsonIgnoreProperties JPA - Not ignoring properties

I am having a faq entity as below. Here createdBy field is having a manyToOne relationship with the user entity. Below joinColumns shows the association.
In the User entity, i have OneToMany relationship with UserRoles and UsersUnit which is EAGER load for User and not for faq. So i added #JsonIgnoreProperties
for UsersUnit and UsersRole and the corresponding User entity is shown below.
#Entity
#Table(name = "FAQ", catalog="abc")
public class Faq implements Serializable {
public Faq() {
super();
}
#Column(name = "CREATE_DATE")
private Timestamp createDate;
#Where(clause = "DELETE_DATE is null")
#Column(name = "DELETE_DATE")
private Timestamp deleteDate;
#Column(name = "DELETED_BY")
private BigDecimal deletedBy;
#Column(name = "DOC_BLOB", nullable = false)
#JsonIgnore
private byte[] docBlob;
#Column(name = "DOC_NAME", nullable = false, length = 100)
private String docName;
#Id
private BigDecimal id;
#Column(name = "ORDER_BY")
private BigDecimal orderBy;
#Column(name = "UPDATE_DATE")
private Timestamp updateDate;
#Column(name = "UPDATED_BY")
private BigDecimal updatedBy;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name="created_by", referencedColumnName="id")
})
private User faqCreatedBy;
}
User entity:
#Entity
#Table(name = "USERS", catalog="abc")
#JsonInclude(Include.NON_NULL)
public class User extends EntityLog{
private BigDecimal id;
private BigDecimal edipi;
private String firstname;
private String lastname;
private String email;
..///
private Set<UsersRoles> userRoles;
private Set<UsersUnit> usersUnit;
#Id
#Column(name="id")
public BigDecimal getId() {
return id;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersRoles> getUserRoles() {
return userRoles;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersUnit> getUsersUnit() {
return usersUnit;
}
////...
}
With this change I am expecting the faq to load with User entity but I am not execting UsersRoles and UsersUnit to load.
But that is not what i see. When faq loads it loads User and UsersRoles and UsersUnit. I am using Spring JPA fyi. Any leads what is wrong ? Appreciate any inputs.

MappingException hibernate mapping columns

I'm struggling with following issue:
Caused by: org.hibernate.MappingException: Foreign key
(FKj4uw5b6ekvxc2djohvon7lk7:bi_person_country_countries
[person_country_id])) must have same number of columns as the
referenced primary key (bi_person_country [country_id,person_id])
I created 4 models:
#Table(name = "bi_country")
#Entity
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "bi_person_country", joinColumns = #JoinColumn(name = "country_id"), inverseJoinColumns = #JoinColumn(name = "person_id"))
private Set<Person> persons;
Gender:
#Table(name = "bi_gender")
#Entity
public class Gender {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
public Integer getId() {
return id;
}
Person:
#Table(name = "bi_person")
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "last_name")
private String lastName;
#Column(name = "additional_info")
private String additionalInfo;
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "persons")
private Set<Country> countries;
#ManyToOne
private Gender gender;
PersonCountry:
#Table(name = "bi_person_country")
#Entity
public class PersonCountry {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
private Person person;
#ManyToMany
private List<Country> countries;
You dont need the PersonCountry class here as you are using #ManyToMany in both cases being Person and Country mappings.
If you have to keep it for some reason.. the linking table should not contain #OneToMany / #ManyToMany mappings, so you would have:
#ManyToOne
private Person person;
#ManyToOne
private Country country;
Keep in mind you may need to use #JoinColumn also if the database names are different than person_id and country_id.

Categories

Resources