Joining tables in hibernate - java

I have two tables
Customer Rate
------------- -----------
res_number product
strategy name
fname type
lname rate
..... ......
And I created two beans
1. 2.
#Entity #Entity
#Table(name="customer") #Table(name="rates")
EmployeeDetails{ CardDetails{
#Col(name="res_number") #col(name="product")
String resNum; String product;
..... ....
} }
Now the query I have is
hql = "from CardDetails cd, EmployeeDetails ed where ed.strategy = cd.product".
But it gives me reference problems saying hibernate.QueryException: could not resolve property:
I have tried adding
#OneToOne(mappedBy = "strategy")
#Cascade(value = CascadeType.ALL)
private EmployeeDetails empDetails;
in CardDetails but it gives me error saying no OneToOne is possible ani... tried changing to ManyToOne and OneToMany but doesnot work. Can anyone please tell me how to map the beans for join using annotations? Note: The database is not designed correctly and there is no common field in both tables(like a foreign key). So any help is greatly appreciated.
EDIT:
Adding the beans:
#Entity
#Table(name="rates")
public class CardDetails {
#Id
#Column(name="CARD_NAME")
String cardName;
#Column(name="CARD_TYPE")
String cardType;
#Column(name="FAQ_PAGE")
String faqPage;
#Column(name="GEN_INTRO_DISCL")
String genIntroDiscl;
#Column(name="GEN_REGULAR_RATE")
String genRegularRate;
#Column(name="BT_FEE")
String btFee;
#Column(name="BONUS")
String bonus;
#Column(name="ART_WORK")
String artWork;
#Column(name="DISCLOSURE_LINK")
String disclosureLink;
#Column(name="TERMS_LINK")
String termsLink;
#Column(name="PRODUCT")
String product;
#Entity
#Table(name="CUSTOMER")
#SecondaryTable(name="APPLICANT")
public class EmployeeDetails {
#Id
#Column(name="RESERVATION_NUMBER")
String reservNumber;
#Column(name="SSN")
int ssnNumber;
#Column(name="BANK_NUMBER")
String bankNumber;
#Column(name="BRANCH_NUMBER")
String branchNumber;
#Column(name="EMPLOYEE_ID")
String empId;
#Column(name="STRATEGY")
String strategy;

From the looks of your HQL, you'd like to join the two tables using stratety in the Customer table and product in the Rate table. This would imply that strategy is a foreign key.
If this is indeed a one-to-one relationship, then inside of CardDetails, try this:
#OneToOne
#JoinColumn(name = "product", referencedColumnName = "strategy")
private EmployeeDetails employeeDetails;
This assumes you don't already have product mapped as a property in CardDetails, if you do, you'll need to do it this way, otherwise Hibernate will complain about duplicate field mappings.
#Column(name = "product", columnDefinition = "char")
private String product;
#OneToOne
#JoinColumn(name = "product", referencedColumnName = "strategy", insertable = false, updatable = false)
private EmployeeDetails employeeDetails;
If it needs to be a one-to-many relationship, then do it this way:
#Column(name = "product", columnDefinition = "char")
private String product;
#OneToMany
#JoinColumn(name = "product", referencedColumnName = "strategy", insertable = false, updatable = false)
private List<EmployeeDetails> employeeDetails;

Related

How can I map these entities using hibernate? Need to map one to many relationship. Foreign key is not updating

In this case, I have 2 entities (Users table and UploadRecord table). I need to map a one-to-many relationship because one user can have many upload records. I need to use UserId as the primary key in the Users table and a foreign key as the UploadRecord table.
I tried using this code but the UploadRecord table fk_UserId is not updating. How to fix this issue?
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "fk_UserId", referencedColumnName = "UserId")
private List<UploadRecord> uploadRecord;
I wrote Users entity class and UploadRecord entity class as follows.
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name= "UserId")
private Long UserId;
#Column(nullable = false, unique = true, length = 45)
private String email;
#Column(name = "fullName", nullable = false, length = 20)
private String fullName;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "fk_UserId", referencedColumnName = "UserId")
private List<UploadRecord> uploadRecord;
//Getters and setters
#Entity
#Table(name = "uploadrecord")
public class UploadRecord {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long uploadRecordId;
#Column(nullable = false, unique = false, length = 1000)
private String fileName;
//Getters and setters
It seems you haven't finished modelling the relationship between these two entities.
Edit your models like this:
User:
#OneToMany(mappedBy="user", cascade = CascadeType.ALL)
private List<UploadRecord> uploadRecords;
UploadRecord :
#ManyToOne
#JoinColumn(name = "userId")
private User user;
More details for modelling relations: Baeldung
Moreover keep an eye on naming convention:
UserId -> userId
uploadRecord -> uploadRecords (Lists, Sets, ...) -> plural

Hibernate get parent child lazy loading with addtional check

I have two tables Company and Employees, one-to-many mapping. Company table contains composite primary key.
I want to search from company table based on primary id but want to put an additional check on the child table.
I want to load only a particular type of employees which I will get in the request. How it can be done in Sprongboot JPA with findById("id");
class Company{
#Id
private String companyId;
#Id
private String stateId;
private String company Name;
#OneToMany(targetEntity = Employees.class, fetch = FetchType.LAZY, cascade = {
CascadeType.ALL }, mappedBy = "company")
private Set<Employees> empList;
}
class Employees{
#Id
private String id;
//foreign key
private String companyId;
//foreign key
private String stateId;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "companyId", referencedColumnName = "companyId", insertable = false, updatable = false, nullable = true),
#JoinColumn(name = "stateId", referencedColumnName = "stateId", insertable = false, updatable = false, nullable = true) })
private Company company;
private int salary;
private String type;
}
Use Filter, which is an alternative of #Where where you can set dynamic value.
Here is the sample
#FilterDef(
name = "employeeTypeFilter",
parameters = #ParamDef(name = "type", type = "string")
)
#Filter(
name = "employeeTypeFilter",
condition = "type > : type"
)
public class Employees {
}
You can enable or disable filter from your code dynamically based on your requirement.
You can use #Where for fixed type
#Where(clause = "type = 'anyEmployeeType'")
private Set<Employees> empList;
For dynamically fetch you can query in Employees repository
List<Employees> findByTypeAndCompany(String type, Company company);

Spring Data JPA delete from many to many relationship problem

In my project I use Spring data jpa. I have tables for many to many relationship. My entities:
#Entity
#Table(name = "SPEC")
public class SpecJpa {
#Id
private int id;
#Column(name = "NAME")
private String name;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "Creator_ID", unique = false, nullable = false, updatable = true)
private UsersJpa usersJpa;
#Column(name = "DESCRIPTION")
private String description;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name="SPEC_PARTS",
joinColumns = #JoinColumn(name="ID_PARTS", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="ID_SPEC", referencedColumnName="id")
)
private Set<PartsJpa> partsJpa;
//---------------
And Parts:
#Entity
#Table(name = "PARTS")
public class PartsJpa {
#Id
private int id;
#Column(name = "NAME")
private String name;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "ID_EXPORT", unique = false, nullable = false, updatable = true)
private ExportJpa exportJpa;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "ID_TYPE", unique = false, nullable = false, updatable = true)
private TypesJpa typesJpa;
#Column(name = "DESCRIPTION")
private String description;
#ManyToMany(fetch = FetchType.EAGER)
private Set<SpecJpa> specJpa;
Now in Controller I try to delete one row from table parts:
#PostMapping("deletePart")
public String deletePart(#RequestParam String id, Model model) {
partsService.deleteById(Integer.parseInt(id));
return "redirect:/parts";
}
But I have exception:
ferential integrity constraint violation:
"FK9Y4MKICYBLJWPENACP4298I49: PUBLIC.PARTS FOREIGN KEY(ID_EXPORT)
REFERENCES PUBLIC.EXPORT(ID) (1)"; SQL statement: /* delete
com.aleksandr0412.demo.entitiesjpa.ExportJpa / delete from EXPORT
where id=? [23503-200]], SQL: / delete
com.aleksandr0412.demo.entitiesjpa.ExportJpa */ delete from EXPORT
where id=? 2020-05-25 19:16:31.630 WARN 13387 --- [nio-8080-exec-4]
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23503, SQLState:
23503
In my db for this entities I have 3 tables: Parts, Spec and Spec_parts. As I understand to solve this problem, I firstly should delete rows in table spec_parts, and after this I can delete row from table parts. How can I do this?
In your partsService implementation, I would recommend you first fetch the resource you are about to delete (i.e the PartsJpa) using the given id from the controller.
Next set its specJpa to null or emptySet, then call the delete method afterwards.
For this to work, ensure that method setSpecJpa(SpecJpa specJpa) and setPartJpa(PartJpa partJpa) are properly implemented.
I hope you find this helpful.

Can we created #CollectionTable inside #Entity class which class is used as CollectionTable in some other #Entity class

I have #Entity class as
#Entity
#Table(name = "EMPLOYEE")
public class Emplyee
{
#Id
#Column(name = "ID", length = 50)
private String id;
#Column(name = "ID", length = 50)
private String name;
#CollectionTable(name = "Address", joinColumns = #JoinColumn(name = "ID"),
indexes = #Index(name = "Address_FK_IDX", columnList = "ID"),
foreignKey = #ForeignKey(name = "EMPLOYEE_Address_FK"))
#Column(name = "EXPORT_FORMAT", length = 50)
private List<Address> address;
}
I want to create Address entity which will hold below attributes
String addressLine;
String city;
String pinCode;
List<String> phoneNo;
In this entity class I want to store list of phoneNo inside another collection table.
Can we do this using #CollectionTable or is there any other way to do this?
You can do this as below. CollectionTableis normally used for collections of embeddable items rather than entities. You'd need to read up on the difference. While there is a good case for making Address an embeddable here rather than an entity, that would cause issues with the phone numbers so we make Address an Entity mapped to Employee using #OneToManyand use ElementCollection within Address for phone numbers.
#Entity
#Table(name = "EMPLOYEE")
public class Employee
{
#Id//<-need to specify a generator here
#Column(name = "ID", length = 50)
private String id;
#Column(name = "ID", length = 50)
private String name;
#OneToMany(cascade = CascadeType.ALL)
//define FK column in Address table
#JoinColumn(joinColumns = #JoinColumn(name = "EMPLOYEE_ID"),
foreignKey = #ForeignKey(name = "EMPLOYEE_Address_FK"))
private List<Address> address;
}
Address:
#Entity
#Table("Address")
public class Address {
#Id //<-need to specify a generator here
private Long id;
String addressLine;
String city;
String pinCode;
#ElementCollection
#CollectionTable(name = "Phone", joinColumns = #JoinColumn(name = "ADDRESS_ID"), foreignKey = #ForeignKey(name = "PHONE_Address_FK"))
List<String> phoneNo;
}
As noted above, #CollectionTable is normally used with collections of embeddables and while there is a case for making Address an #Embeddable rather than an #Entity that would cause issues as the JPA spec (2.6) notes:
An embeddable class (including an embeddable class within another
embeddable class) that is contained within an element collection must
not contain an element collection, nor may it contain a relationship
to an entity other than a many-to-one or one-to-one relationship. The
embeddable class must be on the owning side of such a relationship and
the relationship must be mapped by a foreign key mapping. (See Section
2.9.)

JPA #SecondaryTable foreign key violation

I want to map two entities in a one to many fashion.
A->[B, B]
I want to add to the join table more fields. Pojos looks like:
#Entity
#Table(name = "A", schema = "examples")
#SecondaryTable(name = "A_B", pkJoinColumns = #PrimaryKeyJoinColumn(name = "a_id", referencedColumnName = "id"))
public class A
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Basic
private String name;
#Basic
private Integer field1;
#Column(table = "A_B", name = "field2")
private Integer field2;
#OneToMany(cascade = {CascadeType.ALL})
#JoinTable(name = "A_B", joinColumns = {#JoinColumn(name = "a_id")}, inverseJoinColumns = {#JoinColumn(name = "b_id")})
private List<B> datastores;
}
#Entity
#Table(name = "B", schema = "examples")
#SecondaryTable(name = "A_B", pkJoinColumns = #PrimaryKeyJoinColumn(name = "b_id", referencedColumnName = "id"))
public class B
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Basic
private String field1;
#Basic
private int field2;
#Column(table = "A_B", name = "field3")
private int field3;
}
Thing is that in order to add I had to remove the foreign key on A_B table. How do I solve the mapping to allow the foreign keys ?
Thanks.
I am missing something, but I don't see why both Entity A and Entity B are mapping to table "A_B". By adding it to Entity A as a secondary table, you are stating that every time an insert to Table a occurs, an insert to table A_B must also occur - creating a strict 1:1 relation between rows in the two tables. Except that you do the same thing to entity B, so you will end up with rows in A_B with A_id=somevalue, and B_id= null and others with a_id=null while b_id=somevalue. Table "A_B" looks like a relation table, so this probably isn't what you want.
If A_B is a relationtable you should map it using a ManyToMany as you have for the "A_B" table. If there are extra fields that need to be populated, create a AB Entity, and create a OneToMany from A->AB and B->AB, and ManyToOne from AB->A and AB->B.

Categories

Resources