JPA merge table - spring-boot

I have table employee
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="emp_id")
private Long id;
#Column(name="emp_name")
private String empName;
#Column(name="emp_mail")
private String empMail;
#Column(name="emp_no")
private String empNo;
#Column(name="emp_salary")
private Long empSalary;
#Column(name="type_id")
private Long typeId;
}
In addition, I have table employeetype whose primary key type id is in employee table
How i am able to get response containg type_name not type_id in java data jpa for api using jparepository.
how to join table data.

Related

Spring JPA save() inserting instead of updating

I have a table in below format
Customer:
ID PK
value1
value2
address
I have unique constraint for value1 and value2.
While saving/updating I will not be having value for ID
So here is my service class code to update customer:
#Transactional
public void saveCustomer(String value1,String value2, String address) {
Customer customer = customerRepository.findByValue1AndValue2(value1,value2).orElse(new Customer());
customer.setValue1(value1);
customer.setValue2(value2);
customer.setAddress(address);
customerRepository.save(customer);
}
I am getting "Cannot insert duplicate key row in object error."
When I get the customer object using findByValue1AndValue2, it will have id orrect? so it should do update not insert
Adding my customer class:
#Entity
#Table(name = "customer")
#Data
#NoArgsConstructor
#AllArgsConstructor
#EntityListeners(AuditingEntityListener.class)
public class Customer{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name="value1")
private String value1;
#Column(name="value2")
private String value2;
#Column(name="address")
private String address;
#CreatedDate
#Column(name="created_date", nullable = false, updatable = false)
private Date created_date;
#LastModifiedDate
#Column(name="updated_date")
private Date updated_date;
}
I have added annotation #EnableTransactionManagement
Is there any thing specific need to be done
Please help me with this issue.
Thanks in advance

Is that possible in spring boot that join column (foreign key) with id

I want to join column without object reference. is that possible?
I want to do foreign key without object reference like that
#Data
#Entity
#Table(name = "HRM_EMPLOYEE_SALARY_INCREMENT")
public class EmployeeSalaryIncrement implements Serializable {
private static final long serialVersionUID = 9132875688068247271L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="ID")
private Integer id;
#Column(name = "REFERENCE_NO")
private String referenceNo;
#ManyToOne
#JoinColumn(name = "AUTHORITY", referencedColumnName = "id")
private Integer authority;
#ManyToOne
#JoinColumn(name = "PART_TWO_REGISTER_ID")
private Integer partTwoRegisterId;
#Column(name = "PART_TWO_ORDER_NO")
private String partTwoOrderNo;
#Column(name = "REMARKS")
private String remarks;
#Column(name = "HRM_TYPE")
private Integer hrmType;
}
If I found solve this problem, it will helpful for me.
Joining is not needed in this case. If you only need the foreign key value, then simply add the column as a #Column like any other:
#Data
#Entity
#Table(name = "HRM_EMPLOYEE_SALARY_INCREMENT")
public class EmployeeSalaryIncrement implements Serializable {
private static final long serialVersionUID = 9132875688068247271L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="ID")
private Integer id;
#Column(name = "AUTHORITY")
private Integer authority;
// other fields
// ...
}
No, I don't think that you can join columns between two entities without adding the reference of one to the related entity. You will have to create one entity class corresponding to each of your relational database table and add the reference of one to the other to establish relation.
However, I understand that you may not need all the attributes from your related table based upon your use case, and only wish to select one column from it. You can do that either by only adding required attributes in your joined table entity class (if you are sure you won't need other attributes for that table anywhere else).
Or you can use custom queries using JPQL in your repository class which selects only the required attributes from the tables that you have joined.
I will show you an example of the second way:
//Say, this is your entity class where you wish to join other table to fetch only one attribute from the joined table-
#Entity
#Table(name = "TABLE1", schema = "SCHEMA1")
public class Table1 {
#Id
#Column(name = "ID")
private String id;
#Column(name = "TABLE2_COLUMN")
private String table2Column;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "TABLE2_COLUMN1")
private Table2 table2; //refrence of the joined table entity object
}
// And this is the joined table entity class
#Entity
#Table(name = "TABLE2", schema = "SCHEMA1")
public class Table2 {
#Id
#Column(name = "ID")
private String id;
#Column(name = "TABLE2_COLUMN1")
private String table2Column1;
#Column(name = "TABLE2_COLUMN2")
private String table2Column2; // The column which we want to select from the joined table
}
In your repository class -
#Repository
public interface Table1Repository extends JpaRepository<Table1, String> {
#Query("SELECT t1 FROM Table1 t1 WHERE t1.id = :id")
public List<Table1> getTable1Rows(#Param("id") String id);
#Query("SELECT t1.table2.table2Column2 FROM Table1 t1 WHERE t1.id = :id")
public String getTable2Column2(#Param("id") String id);
}
Based upon the response from Markus Pscheidt below, I agree when he said there's no need to join the entities if you only need the attribute which is a foreign key. As foreign key is already present as an attribute in your entity (or table) you are working with.
If you need to fetch any other column apart from foreign key, then you may use JPQL to fetch the exact column that you wish to select.

Many to one relationship without a join table in spring

I'm trying to build the relationship between two tables using spring-data jpa. I have read many SO articles like 1, 2 but they are pretty old and don't seem to apply to my specific use case. Hence this question:
There are 2 tables user_client_scopes and scopes listed below.
user_client_scopes:
user_id (long),
client_id (string)
last_updated (timestamp)
scope_id (Foreign key to scopes table),
primary key (user_id, client_id, scope_id)
scopes:
id (int, primary key)
name (string)
A <user_id, client_id> can have multiple scopes. Similarly, the same scope can be held by many <user_id, client_id>s. Hence the many-to-many relationship. The join table (as defined by spring-data-jpa) is kind of embedded within user_client_scope table.
Here is a half-written-code:
#Entity
#Table(name = "user_client_scopes")
#RequiredArgsConstructor
#IdClass(UserClientScopesPK.class)
public class UserClientScopes implements Serializable {
#Id
#Column(name = "user_id")
private long userId;
#Id
#Column(name = "client_id")
private String clientId;
#Column(name = "last_updated")
private Timestamp lastUpdated;
#Id
#Column(name = "scope_id")
private int scopeId;
#ManyToMany // <- how to complete this definition?
private Set<Scope> scopes;
getters and setters.
Here are 2 other classes (for the sake of completion).
#Data
#RequiredArgsConstructor
public class UserClientScopesPK implements Serializable {
private long userId;
private String clientId;
private int scopeId;
}
#Entity
#Table(name = "scopes")
#RequiredArgsConstructor
public class Scope implements Serializable {
#Id
#GeneratedValue
private long id;
private String name;
}
How do I complete the user_client_scopes entity such that we can:
Find all scopes for a given <user_id, client_id>. i.e. execute the following SQL:
select user_id, client_id, scope
from scopes
join user_client_scopes ucs on ucs.scope_id = scopes.id
where ucs.user_id = ? and ucs.client_id = ?
Save new scopes for a given <user_id, client_id>. i.e. execute the following SQL:
insert into user_client_scopes (user_id, client_id, scope_id, last_updated)
select ?, ?, id, now()
from scopes
where scopes.name = ?
UPDATE 1:
Changing title to Many to one instead of Many to many relationship.
That's not a many-to-many because the association scope is mapped by the column scope_id in user_client_scopes. This means that if I take a single row in the table user_client_scopes, it will be associated to only a single row in the table scopes. Therefore, this is a many-to-one.
If the three columns <user_id, client_id, scope_id> form the key for user_client_scopes, then the mapping for the table should look like:
Entity
#Table(name = "user_client_scopes")
#RequiredArgsConstructor
#IdClass(UserClientScopesPK.class)
public class UserClientScopes implements Serializable {
#Id
#Column(name = "user_id")
private long userId;
#Id
#Column(name = "client_id")
private String clientId;
#Column(name = "last_updated")
private Timestamp lastUpdated;
#Id
#ManyToOne
#JoinedColumn(name = "scope_id")
private Scope scope;
getters and setters.
}
class UserClientScopesPK implements Serializable {
private long userId;
private String clientId;
private Scope scope;
// getters,setters, equals and hascode
}
With this mapping you can run the following HQL:
select ucs
from UserClientScopes ucs join ucs.scope
where ucs.userId = :userId and ucs.clientId = :clientId
It will return all UserClientScopes entities matching the selected pair <userId, clientId>. Each one with a different scope.
Or, if you only care about the scope:
select s
from UserClientScopes ucs join ucs.scope s
where ucs.userId = :userId and ucs.clientId = :clientId
With Spring Data JPA, it will look like this:
#Query("select s from UserClientScopes ucs join ucs.scope swhere ucs.userId = ?1 and ucs.clientId = ?2")
public List<Scope> findScopesByUserIdAndClientId(long userId, String clientId);
or
#Query("select s.name from UserClientScopes ucs join ucs.scope swhere ucs.userId = ?1 and ucs.clientId = ?2")
public List<String> findScopesNameByUserIdAndClientId(long userId, String clientId);
You can also run the insert query as native SQL (you can probably run something similar as HQL, but I don't remember the right syntax now. I will update the answer later).
One last thing, to keep track of the last updated time, you could use Spring Entity callback listener:
#Entity
...
#EntityListeners(AuditingEntityListener.class)
public class UserClientScopes implements Serializable {
#LastModifiedDate
#Column(name = "last_updated")
private Date lastUpdated;
}

Remove rows mappedBy a foreign key of another table

I have two tables Company and Employees. They have a 1-many relation. I want to delete all rows from Company and set null the column with foreign-key from Employees.
#Entity
public class Employees{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int empId;
#ManyToOne
#JoinColumn(name="company_id")
private Company company;
}
#Entity
public class Company{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int comId;
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private List<Employees> employees = new LinkedList<>();
}
public interface CompanyRepository extends JpaRepository<Company, Integer> {
}
public interface EmployeesRepository extends JpaRepository<Employees, Integer> {
}
In controller if I just delete Company rows with #AutowiredCompanyRepository companyRepo; companyRepo.deleteAll(); it shows of course:
Cannot delete or update a parent row: a foreign key constraint fails.
I tried to write an update in EmployeesRepository over Employees to set company.comId to null, because I want to keep the rows, except comId field. In EmployeesRepository I wrote:
#Modifying
#Query("UPDATE Employees e SET e.company.comId=null")
void removeCompanyId();
It caused the following error:
javax.persistence.TransactionRequiredException: Executing an update/delete query

Spring: relation data many-to-one

i have first entity :
#Entity
#Table(name="TABLE_ONE")
public class TableOne implements Serializable {
#Id
#Column(name="ID")
private Integer id;
#ManyToOne
#JoinColumn(name="TABLE_TWO_ID", nullable = false)
private TableTwo tableTwoId;
and the second table entity :
#Entity
#Table(name="TABLE_TWO")
public class TableTwo{
#Id
#Column(name="ID")
private Integer id;
, but then after i compile , the result is :
ERROR: column "table_two_id" does not exist
I want to get ID from TableTwo.
Joincolumn annotation tells hibernate the foreign key join column name, in this case I guess it's ID.

Resources