Hibernate Join Table - java

i have a MySQL database which is updated from Java with Entities.
I need a join table between two tables which contains 3 columns.
1 column from table Bar ("bar_id")
2 columns from table Owner ("owner_id", "bought")
Could you please tell me if that is possible or how I could realize that.
I want a join table which looks like this:
'bar_id' | 'owner_id' | 'bought'
--------------------------------
BaseEntity.java
#MappedSuperclass
public class BaseEntity {
private int id;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId(){ return this.id; }
public void setId(int id){ this.id = id; }
}
Bar.java
#Entity
#Table(name="bar")
public class Bar extends BaseEntity{
private String name;
private String bought;
private List<Fan> fan;
private List<Owner> owner;
#Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="bought")
public String getBought() {
return bought;
}
public void setBought(String bought) {
this.bought = bought;
}
#ManyToMany(mappedBy="bar", targetEntity=Owner.class)
public List<Owner> getOwner() {
return owner;
}
public void setOwner(List<Owner> owner) {
this.owner = owner;
}
#ManyToMany
#JoinColumn(name="fan")
public List<Fan> getFan() {
return fan;
}
public void setFan(List<Fan> fan) {
this.fan = fan;
}
}
Owner.java
#Entity
#Table(name="owner")
public class Owner extends BaseEntity{
private String firstname;
private String lastname;
private String birthday;
private java.sql.Date bought;
private List<Bar> bar;
#Column(name="firstname")
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
#Column(name="lastname")
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
#Column(name="birthday")
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
#Column(name="bought")
public java.sql.Date getBought() {
return bought;
}
public void setBought(java.sql.Date bought) {
this.bought = bought;
}
#ManyToMany
#JoinColumn(name="bar")
public List<Bar> getBar() {
return bar;
}
public void setBar(List<Bar> bar) {
this.bar = bar;
}
}

You can create a Join table by the using #JoinTable annotation.
Please have a look at this post which explains how to achieve it.
How to create join table with JPA annotations?

Related

Why projection fields are not getting set while fetching data using projection by joining two unrelated entities in JPA?

I am trying to get some specific column values using projection by joining two unrelated entities. But I am not getting any values.
Repository code is:-
#Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
#Query("SELECT p.id,p.firstName,p.lastName,a.city FROM Person p INNER JOIN Address a on p.id = a.personId")
public List<PersonAndAddressSummary> findAllPersonSummary();
}
Person class
#Entity
public class Person {
#Id
private long id;
private String firstName;
private String lastName;
private long phone;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
}
Address class
#Entity
public class Address {
#Id
private int id;
private String street;
private String state;
private int personId;
private String country;
private int houseNo;
private String city;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getHouseNo() {
return houseNo;
}
public void setHouseNo(int houseNo) {
this.houseNo = houseNo;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Projection interface
public interface PersonAndAddressSummary {
public String getId();
public String getFirstName();
public String getLastName();
public String getCity();
}
After executing this Spring Boot application, the output I am getting is this.
[{"lastName":null,"firstName":null,"city":null,"id":null},{"lastName":null,"firstName":null,"city":null,"id":null},{"lastName":null,"firstName":null,"city":null,"id":null}]
Though there are records available which match perfectly for each Person in Address class(data available in person and address table).
If there is no join between two entities then you can't get data of other entity.Every repository is class specific in jpa. You have to define different projection for each class.
#Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
#Query("SELECT p FROM Person p")
public List<PersonAndSummary> findAllPersonSummary();
}
#Repository
public interface AddressRepository extends CrudRepository<Address, Long> {
#Query("SELECT a FROM Address a where a.personId=:personId")
public AddressSummary findAddressSummary(#Param("personId") int personId);
}
public interface PersonSummary {
public String getId();
public String getFirstName();
public String getLastName();
}
public interface AddressSummary {
public String getCity();
}
public interface PersonAndAddressSummary extends PersonSummary, AddressSummary{
}
Now in your service class find list of personSummary. Now iterate this list and get AddressSummary by personId.
List<PersonSummary> personSummaryList = yourRepositoryName.findAllPersonSummary();
List<PersonAndAddressSummary> list = new ArrayList<>();
for(PersonSummary summary: personSummaryList){
AddressSummary addressSummary = repositoryName.findAddressSummary(summary.getId());
//now add required fields in your list
}

OneToOne Bi-Directional Mapping using Hibernate annotation

I want a Bi-Directional mapping on my 2 Entities(PersonDetail,
PassportDetail) but it seems that it doesn't work fine. I want that
PersonDetail has a PassportId and PassportDetail has a PersonId as well.
My PersonDetail java Code
#Entity
#Table(name="persondetail")
public class PersonDetail {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="person_id")
private int id;
#Column(name="person_name")
private String name;
#Column(name="person_phone")
private long phone;
#OneToOne(mappedBy="person",cascade=CascadeType.ALL)
#JoinColumn(name="passport_id")
private PassportDetail passport;
public PassportDetail getPassport() {
return passport;
}
public void setPassport(PassportDetail passport) {
this.passport = passport;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
#Column(name="passport_id")
private int passort_id;
public int getPassort_id() {
return passort_id;
}
public void setPassort_id(int passort_id) {
this.passort_id = passort_id;
}
}
Here is my PassportDetail Java Code
#Entity
#Table(name="PassportDetail")
public class PassportDetail {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="passport_id")
private int id;
#Column(name="passport_number")
private String passportNumber;
#Column(name="country_name")
private String country;
#Column(name="issue_date")
#Temporal(TemporalType.DATE)
private Date date;
#OneToOne
#JoinColumn(name="person_id")
private PersonDetail person;
public String getPassportNumber() {
return passportNumber;
}
public void setPassportNumber(String passportNumber) {
this.passportNumber = passportNumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public PersonDetail getPerson() {
return person;
}
public void setPerson(PersonDetail person) {
this.person = person;
}
}
Here is the Output in MySql
Here is the Output of Both table as you can clearly see the problem i.e PersonDetail has a column named passport_id but it dosesn't have any value
Here is the insertion code
public class MappingMain {
public static void main(String[] args) {
PersonDetail person=new PersonDetail();
PassportDetail passport = new PassportDetail();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd");
person.setName("Ankit");
person.setPhone(790148565);
passport.setCountry("india");
try {
passport.setDate(sdf.parse("2018-04-15"));
}
catch(Exception e)
{
}
passport.setPassportNumber("QUJMZ123");
passport.setPerson(person);
person.setPassport(passport);
PersonDao dao=new PersonDao();
dao.save(person);
}
Here is the DAO class
public class MappingDao {
SessionFactory sf=Util.getSessionFactory();
public void save(UserDemo user)
{
Session session=sf.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
}

HQL compare existing Objects tables

I just want to explain following scenario.
I have Registration table for employee
It has one field like BranchAddress, and I have using table Branch for that with ManyToOne mapping.
#Entity
#Table(name = "temp_reg")
public class TemporaryRegistrationDTO {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int ID;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#ManyToOne(cascade=CascadeType.ALL)
private BranchDTO companyBranch;
public BranchDTO getCompanyBranch() {
return companyBranch;
}
public void setCompanyBranch(BranchDTO companyBranch) {
this.companyBranch = companyBranch;
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
#Entity
#Table(name = "company_branch")
public class BranchDTO {
#Id
#GeneratedValue ( strategy = GenerationType.AUTO)
private int branchID;
public int getBranchID() {
return branchID;
}
public void setBranchID(int branchID) {
this.branchID = branchID;
}
#ManyToOne(cascade=CascadeType.ALL)
private CountriesDTO country;
#ManyToOne(cascade=CascadeType.ALL)
private StatesDTO state;
public CountriesDTO getCountry() {
return country;
}
public void setCountry(CountriesDTO country) {
this.country = country;
}
public StatesDTO getState() {
return state;
}
public void setState(StatesDTO state) {
this.state = state;
}
}
#Entity
#Table(name = "company_countries")
public class CountriesDTO {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String countryCode;
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
private String countryName;
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
}
#Entity
#Table(name = "company_states")
public class StatesDTO {
#Id
#GeneratedValue ( strategy = GenerationType.AUTO)
private int state_id;
private String state;
private String stateCode;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getStateCode() {
return stateCode;
}
public void setStateCode(String stateCode) {
this.stateCode = stateCode;
}
#Override
public String toString() {
return "StatesDTO [statesID=" + state_id + ", state=" + state + ", stateCode=" + stateCode + "]";
}
public int getState_id() {
return state_id;
}
public void setState_id(int state_id) {
this.state_id = state_id;
}
}
Now, What I want is that, whenever their is request for registration, Firstly I am checking if Branch Address is available in the Branch table. If it contains an entry already, then it will retrieve Branch row and stooping from same data to Branch Table
Now, to check for BranchDTO, I have created method in Branch Repository class.
#Query("from BranchDTO where country = :country and state = :state")
public BranchDTO existsEntry(#org.springframework.data.repository.query.Param("country") CountriesDTO country,#org.springframework.data.repository.query.Param("state") StatesDTO state);
But It reflects me following error,
object references an unsaved transient instance - save the transient instance before flushing: com.example.demo.pojo.CountriesDTO
Thank you guys

How to populate foreign key in table Spring + Hibernate + Spring Security

I want make a case, when user is authenticated by Spring Security and then he fill adres form I would like to automatically updated a foreign key column "adres_id" in user table. Please give me a tip how implement this in the most popular way
I how somethig like this
Address Table:
User Table:
Adres
#Entity
#Table(name="adres")
public class Adres {
#Id
#GeneratedValue(strategy = GenerationType.AUTO )
int id;
#Column(name="country", nullable=false)
private String country;
private String street;
private String postcode;
private String telephone;
private String pesel;
#OneToOne(mappedBy ="adres")
private User user;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getPesel() {
return pesel;
}
public void setPesel(String pesel) {
this.pesel = pesel;
}
public String getStreet() {
return postcode;
}
public void setStreet(String street) {
this.street = street;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
User
#Entity
#Table(name="users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO )
int id;
#Column(name="username", nullable=false)
private String username;
private String password;
private String email;
private Boolean enabled;
#OneToOne(cascade = CascadeType.ALL)
private Adres adres;
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
AdresDAO
#Repository
#Transactional
public class AdresDAOImpl implements AdresDAO{
#Autowired
SessionFactory sessionFactory;
public void addAdres(Adres adres) {
sessionFactory.getCurrentSession().save(adres);
}
public List<Adres> listAdres() {
return sessionFactory.getCurrentSession().createQuery("from Adres order by id").list();
}
public void removeAdres(int id) {
Adres adres = (Adres) sessionFactory.getCurrentSession().load(
Adres.class, id);
if (null != adres) {
sessionFactory.getCurrentSession().delete(adres);
}
}
public Adres getAdres(int id) {
return (Adres)sessionFactory.getCurrentSession().get(Adres.class, id);
}
public void editAdres(Adres adres) {
sessionFactory.getCurrentSession().update(adres);
}
}
AdresService
#Service
public class AdresServiceImpl implements AdresService{
#Autowired
AdresDAO adresDAO;
#Transactional
public void addAdres(Adres adres) {
adresDAO.addAdres(adres);
}
#Transactional
public void editAdres(Adres adres) {
adresDAO.editAdres(adres);
}
#Transactional
public List<Adres> listAdres() {
return adresDAO.listAdres();
}
#Transactional
public void removeAdres(int id) {
adresDAO.removeAdres(id);
}
#Transactional
public Adres getAdres(int id) {
return adresDAO.getAdres(id);
}
}
User unidirectional relation between User and Address if Address object does not supposed to know about its owner (generally it does not). I would prefer user id in Address table if a User have more than one Address (one-to-many relation).
But for your question you may design like that,
public class User{
...
#OneToOne(CascadeType.REMOVE)//this is for to remove address when user is removed
#JoinColumn(name="HOME_ADDRESS_ID")
private Address address;
...
}
and
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO )
int id;
#Column(name="country", nullable=false)
private String country;
private String street;
private String postcode;
private String telephone;
private String pesel;
//no user object here
public int getId() {
return id;
}
...
}

Enable DefaultPersistEventListener in Hibernate

I'm trying to delete a object in Hibernate and for some reason its not getting deleted..
Now, I want to enable the DefaultPersistEventListener and really want to understand what is the problem but im not sure how to do it?
Emp1000 e1 = new Emp1000();
e1.setId(1067);
session.delete(e1);
System.out.println("delete over");
Employee table
#Entity
#NamedQuery(name = "Emp1000.findAll", query = "SELECT e FROM Emp1000 e")
public class Emp1000 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
// bi-directional many-to-one association to EmpDept
// #OneToMany(mappedBy="emp1000")
// #OneToMany(mappedBy="emp1000", cascade = CascadeType.MERGE)// Cascade merge and you need to explicitly save it
#OneToMany(mappedBy = "emp1000", cascade = CascadeType.ALL) // Cascade merge and you need to explicitly save it
#Fetch(FetchMode.SELECT) //Lazy loading
//#Fetch(FetchMode.JOIN)
private List<EmpDept> empDepts;
public Emp1000() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<EmpDept> getEmpDepts() {
return this.empDepts;
}
public void setEmpDepts(List<EmpDept> empDepts) {
this.empDepts = empDepts;
}
public EmpDept addEmpDept(EmpDept empDept) {
getEmpDepts().add(empDept);
empDept.setEmp1000(this);
return empDept;
}
public EmpDept removeEmpDept(EmpDept empDept) {
getEmpDepts().remove(empDept);
empDept.setEmp1000(null);
return empDept;
}
}
Emp_Dept
#Entity
#Table(name="emp_dept")
#NamedQuery(name="EmpDept.findAll", query="SELECT e FROM EmpDept e")
public class EmpDept implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String dept;
//bi-directional many-to-one association to Emp1000
#ManyToOne
#JoinColumn(name="emp_id")
private Emp1000 emp1000;
public EmpDept() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getDept() {
return this.dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public Emp1000 getEmp1000() {
return this.emp1000;
}
public void setEmp1000(Emp1000 emp1000) {
this.emp1000 = emp1000;
}
}
First you need to make sure your code execute inside the transaction and commit after that. If that is, use session.flush() to synchronized system state with database.
Details are explaining in this thread.
Question about Hibernate session.flush()

Categories

Resources