В этой статье показаны различные способы вызова хранимых процедур из Hibernate.
Действия JDBC не будут покрыты.
PostgreSQL будет использоваться в качестве базы данных.
CREATE DATABASE example;
CREATE TABLE company (
company_id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE benefit (
benefit_id BIGSERIAL PRIMARY KEY,
name TEXT,
company_id BIGINT,
CONSTRAINT fk_company FOREIGN KEY (company_id)
REFERENCES company (company_id) MATCH SIMPLE
);
CREATE TABLE employee (
employee_id BIGSERIAL PRIMARY KEY,
first_name TEXT,
last_name TEXT,
company_id BIGINT,
CONSTRAINT fk_company FOREIGN KEY (company_id)
REFERENCES company (company_id) MATCH SIMPLE
);
CREATE TABLE employee_benefit (
employee_id BIGINT,
benefit_id BIGINT,
CONSTRAINT fk_employee FOREIGN KEY (employee_id)
REFERENCES employee (employee_id) MATCH SIMPLE ,
CONSTRAINT fk_benefit FOREIGN KEY (benefit_id)
REFERENCES benefit (benefit_id) MATCH SIMPLE
);
INSERT INTO company (name) VALUES ('TestCompany');
INSERT INTO employee (first_name, last_name, company_id) VALUES ('Emmanouil','Gkatziouras',1);
INSERT INTO benefit (name,company_id) VALUES ('gym',1);
INSERT INTO benefit (name,company_id) VALUES ('lunch',1);
Наша функция postgresql вернет набор вознаграждений работникам
CREATE OR REPLACE FUNCTION add_all_company_benefits(employeeId BIGINT,companyid BIGINT)
RETURNS TABLE(benefit_id BIGINT,name TEXT,company_id BIGINT) AS $$
DECLARE benefitid BIGINT;
BEGIN
FOR benefitid IN (SELECT benefit.benefit_id FROM benefit WHERE benefit.company_id=companyid) LOOP
IF (SELECT COUNT(*) FROM employee_benefit as eb
WHERE eb.employee_id=employeeid
AND eb.benefit_id=benefitid) = 0
THEN
INSERT INTO employee_benefit (employee_id, benefit_id)
VALUES (employeeId,benefitId);
END IF;
END LOOP;
RETURN QUERY
SELECT benefit.benefit_id,benefit.name,benefit.company_id FROM benefit
INNER JOIN employee_benefit ON employee_benefit.benefit_id = benefit.benefit_id
WHERE employee_benefit.employee_id=employeeId;
END;
$$ LANGUAGE plpgsql;
Отображения сущностей с использованием аннотаций JPA следуют
Субъект компании.
package com.gkatzioura.example.entity;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "company")
public class Company {
@Id
@GeneratedValue
@Column(name = "company_id")
private Long Id;
@Column
String name;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "company")
private Set<Benefit> benefits = new HashSet<Benefit>();
public Long getId() {
return Id;
}
public void setId(Long id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Benefit> getBenefits() {
return benefits;
}
public void setBenefits(Set<Benefit> benefits) {
this.benefits = benefits;
}
}
Сотрудник юридического лица.
package com.gkatzioura.example.entity;
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue
@Column(name = "employee_id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "company_id",referencedColumnName = "company_id")
private Company company;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
Выгода субъекта.
package com.gkatzioura.example.entity;
import javax.persistence.*;
@Entity
@Table(name = "benefit")
public class Benefit {
@Id
@GeneratedValue
@Column(name = "benefit_id")
private Long id;
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
Наш первый подход заключается в вызове процедуры в виде спящего SQL-запроса.
Session session = sessionFactory.openSession();
List<Company> companies = session.createCriteria(Company.class)
.add(Restrictions.eq("name", companyName))
.list();
List<Employee> employees = session.createCriteria(Employee.class)
.add(Restrictions.eq("firstName",employeeName))
.list();
for(Company company:companies) {
for(Employee employee:employees) {
LOGGER.info("The company is "+company.getId()+" the employee is "+employee.getId());
SQLQuery query = (SQLQuery) session.createSQLQuery("SELECT*FROM add_all_company_benefits(:employeeId,:companyId)")
.addEntity(Benefit.class)
.setParameter("employeeId", employee.getId())
.setParameter("companyId", company.getId());
List result = query.list();
for(Integer i=0;i<result.size();i++) {
LOGGER.info("The benefit is "+((Benefit) result.get(i)).getName());
}
}
}
session.close();
We will update the company entity by adding a NameQuery in the company entity.
@Entity
@Table(name = "company")
@NamedNativeQueries({
@NamedNativeQuery(
name = "AddAllCompanyBenefits",
query = "SELECT*FROM add_all_company_benefits(:employeeId,:companyId)",
resultClass = Benefit.class
)
})
public class Company {
}
Our hibernate actions will be refactored to
Query query = session.getNamedQuery("AddAllCompanyBenefits")
.setParameter("employeeId", employee.getId())
.setParameter("companyId", company.getId());
List result = query.list();
for(Integer i=0;i<result.size();i++) {
LOGGER.info("The benefit is "+((Benefit) result.get(i)).getName());
}
Another way is to use hibernate’s ProcedureCall which is used on hibernate’s implementation of JPA’s StoredProcedureQuery
ProcedureCall procedureCall = session.createStoredProcedureCall("add_all_company_benefits");
procedureCall.registerParameter("EMPLOYEE", Long.class, ParameterMode.IN);
procedureCall.registerParameter("COMPANY", Long.class, ParameterMode.IN);
procedureCall.getParameterRegistration("EMPLOYEE").bindValue(employee.getId());
procedureCall.getParameterRegistration("COMPANY").bindValue(company.getId());
ProcedureOutputs procedureOutputs = procedureCall.getOutputs();
ResultSetOutput resultSetOutput = (ResultSetOutput) procedureOutputs.getCurrent();
List results = resultSetOutput.getResultList();
for(Integer i=0;i<results.size();i++) {
Object[] objects = (Object[]) results.get(i);
LOGGER.info("The benefit is "+objects[1]);
}