Upgrade to Hibernate 5.2.1 and Spring Framework 4.3 to pull in the necessary tweaks to let the latter work with the former. Excluded hibernate-entitymanager and refer to hibernate-core instead as the 5.2 release has merged the artifacts and the former is not available anymore. The project showing the stored procedure support still needs to stay on Hibernate 5.0.7 because the stored procedure support on HSQLDB has been broken since 5.0.8. The original issue [0] has been fixed but running the module on 5.2.1 now runs into a NullPointerException from AbstractProducedQuery [1]. [0] https://hibernate.atlassian.net/browse/HHH-10515 [1] https://hibernate.atlassian.net/browse/HHH-10915
Spring Data JPA - JPA 2.1 example
This project contains samples of JPA 2.1 specific features of Spring Data JPA.
Support for stored procedure execution
You can execute stored procedures either predefined using the JPA 2.1 mapping annotations or dynamically let the stored procedure definition be derived from the repository method name.
Stored procedure declaration in the database (schema.sql):
DROP procedure IF EXISTS plus1inout
/;
CREATE procedure plus1inout (IN arg int, OUT res int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
JPA 2.1 stored procedure declaration:
@Entity
@NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) })
public class User {
@Id @GeneratedValue//
private Long id;
}
Spring Data JPA repository declaration to execute procedures:
public interface UserRepository extends CrudRepository<User, Long> {
// Explicitly mapped to named stored procedure {@code User.plus1} in the {@link EntityManager}.
// By default, we would've try to find a procedure declaration named User.plus1BackedByOtherNamedStoredProcedure
@Procedure(name = "User.plus1")
Integer plus1BackedByOtherNamedStoredProcedure(@Param("arg") Integer arg);
// Directly map the method to the stored procedure in the database (to avoid the annotation madness on your domain classes).
@Procedure
Integer plus1inout(Integer arg);
}
Calling UserRepository.plus1BackedByOtherNamedStoredProcedure(…) will execute the stored procedure plus1inout using the meta-data declared on the User domain class.
UserRepository.plus1inout(…) will derive stored procedure metadata from the repository and default to positional parameter binding and expect a single output parameter of the backing stored procedure.