I have a application written in Spring, Hibernate and SpringBoot,
I have 2 entities class with one to many mapping,
Here are my LeadUserDb entity class
#Entity
#Table(name="lead_user_db")
#NamedQuery(name="LeadUserDb.findAll", query="SELECT l FROM LeadUserDb l")
public class LeadUserDb implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="branchcode")
private String branchcode;
#Column(name="reporting_level")
private int reportingLevel;
//bi-directional many-to-one association to UserBasicDetailsDb
#ManyToOne
#JoinColumn(name="email_Id")
private UserBasicDetailsDb userBasicDetailsDb;
public LeadUserDb() {
}
public String getBranchcode() {
return this.branchcode;
}
public void setBranchcode(String branchcode) {
this.branchcode = branchcode;
}
public int getReportingLevel() {
return this.reportingLevel;
}
public void setReportingLevel(int reportingLevel) {
this.reportingLevel = reportingLevel;
}
public UserBasicDetailsDb getUserBasicDetailsDb() {
return this.userBasicDetailsDb;
}
public void setUserBasicDetailsDb(UserBasicDetailsDb userBasicDetailsDb) {
this.userBasicDetailsDb = userBasicDetailsDb;
}
And This is my UserBasicDetailsDb Entity Class
#Entity
#Table(name="user_basic_details_db")
public class UserBasicDetailsDb implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String email;
private String address;
private String city;
private String dob;
private String mobile;
private String name;
private String pan;
private String pincode;
private String state;
#OneToMany(mappedBy="userBasicDetailsDb")
private List<LeadUserDb> leadUserDbs;
public UserBasicDetailsDb() {
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getDob() {
return this.dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getMobile() {
return this.mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPan() {
return this.pan;
}
public void setPan(String pan) {
this.pan = pan;
}
public String getPincode() {
return this.pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public List<LeadUserDb> getLeadUserDbs() {
return this.leadUserDbs;
}
public void setLeadUserDbs(List<LeadUserDb> leadUserDbs) {
this.leadUserDbs = leadUserDbs;
}
public LeadUserDb addLeadUserDb(LeadUserDb leadUserDb) {
getLeadUserDbs().add(leadUserDb);
leadUserDb.setUserBasicDetailsDb(this);
return leadUserDb;
}
public LeadUserDb removeLeadUserDb(LeadUserDb leadUserDb) {
getLeadUserDbs().remove(leadUserDb);
leadUserDb.setUserBasicDetailsDb(null);
return leadUserDb;
}
what i want to achieve is to create a query like this one
SELECT a.branchcode as branchCode,b.name FROM lead_user_db a
inner join user_basic_details_db b
where b.email = a.email_id and a.reporting_level = 3
here is what I have written my Repository class
public interface GetUserList extends CrudRepository<LeadUserDb, Integer> {
#Query(value = "SELECT a.id, a.branchcode as branchCode,b.name as name,a.reporting_level,a.email_id FROM lead_user_db a\n" +
"inner join user_basic_details_db b\n" +
"where b.email = a.email_id and a.reporting_level = ?1", nativeQuery = true)
List<LeadUserDb> findByReportingLevel(int reportingLevel);
}
and this is how I am calling it
UserBasicDetailsDb details = GetUserList.findByReportingLevel(3);
NOTE
Getting a new error Cannot determine value type from string test#dev.com
I am getting a hell lot of data, and the actual output have only 2 records
My question is how can i fetch the list of user based on reportingLevel
Any help would be appreciated
Related
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
}
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();
}
}
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
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;
}
...
}
I have hibernate #OneToMany mapping I am getting the mentioned error. Does not understand the reason. As getters and setters are public
Below are the entities
#Entity
#Table(name="USER_DETAILS")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="USER_FIRSTNAME",nullable=false, length=50)
private String userFirstName;
#Column(name="USER_LASTNAME",nullable=false, length=50)
private String userLastName;
#Column(name="USER_MIDDLENAME",length = 30)
private String userMiddleName;
#Column(name="USER_AGE")
private int userAge;
#Column(name="USER_SEX")
private String userSex;
#OneToMany(cascade=CascadeType.ALL, mappedBy="userAddress", targetEntity=Address.class)
private Set<Address> address = new HashSet<Address>();
public String getUserFirstName() {
return userFirstName;
}
public void setUserFirstName(String userFirstName) {
this.userFirstName = userFirstName;
}
public String getUserLastName() {
return userLastName;
}
public void setUserLastName(String userLastName) {
this.userLastName = userLastName;
}
public String getUserMiddleName() {
return userMiddleName;
}
public void setUserMiddleName(String userMiddleName) {
this.userMiddleName = userMiddleName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
}
#Entity
#Table(name = "ADDRESS")
public class Address implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ADDRESS_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name = "ZIP_CODE")
private String zipCode;
#Column(name="ADDRESS_USER_ID", insertable=false, updatable=false)
private Long addressUserID;
#Column(name = "ADDRESS_SEC")
private String addressSec;
#Column(name = "STREET")
private String street;
#Column(name = "CITY")
private String city;
#Column(name = "COUNTRY")
private String country;
#ManyToOne(cascade=CascadeType.ALL, targetEntity=User.class)
#JoinColumn(name="ADDRESS_USER_ID")
private Set<User> userAddress = new HashSet<User>();
public Long getAddressUserID() {
return addressUserID;
}
public void setAddressUserID(Long addressUserID) {
this.addressUserID = addressUserID;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public Set<User> getUserAddress() {
return userAddress;
}
public void setUserAddress(Set<User> userAddress) {
this.userAddress = userAddress;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAddressSec() {
return addressSec;
}
public void setAddressSec(String addressSec) {
this.addressSec = addressSec;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Part of Stack Trace are:
Exception in thread "main" org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.java.hibernate.practise.User.id at... org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:62)
Caused by: java.lang.IllegalArgumentException: Can not set int field com.java.hibernate.practise.User.id to java.util.HashSet...
I am generating the schema using hibernate.hbm2ddl.auto= cerate-drop
Please guide on this.
Generally when we use 1..n bidirectional entity mapping, the owning side which is in general, the many side, should have only a single instance reference to the one side object (not a collection - that would be many to many), and the join column to use is the primary key from the on side class. We don't need to explicitly use the FK column in the many side like you are.
So if this is your relationship User [1]..[N] Address, then you should have something more like
public class User {
...
#OneToMany(mappedBy = "user", cascade=CascadeType.ALL)
private Set<Address> addresses;
}
public class Address {
// private Long addressUserID; // Don't need this property. We get it below
...
#ManyToOne
#JoinColumn(name = "USER_ID")
private User user;
}