Procedimentos armazenados com o Hibernate
1. Visão geral
Procedimentos armazenados são conjuntos de instruções SQL compiladasresiding in the database.. Eles são usados para encapsular e compartilhar lógica com outros programas e se beneficiar de recursos específicos do banco de dados, como dicas de índice ou palavras-chave específicas.
Este artigo demonstra como usarHibernate para chamarstored procedure emMySQL database.
2. Procedimentos armazenados em MySQL
Antes de discutirmos como chamar um procedimento armazenado do Hibernate, precisamos criá-lo.
Para este exemplo rápido do MySQL, vamoscreate a stored procedure para obter todos os registros de uma tabelafoo.
Para criar um procedimento armazenado, usamos a instruçãoCREATE PROCEDURE:
DELIMITER //
CREATE PROCEDURE GetAllFoos()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT * FROM foo;
END //
DELIMITER;
Antes da instruçãoBEGIN, podemos definir instruções opcionais. Você pode detalhar os detalhes dessas declarações seguindo o link oficialMySQL documentation.
Podemos usar a instruçãoCALL para garantir que nosso procedimento se comporte da maneira desejada:
CALL GetAllFoos();
Agora que temos nosso procedimento armazenado instalado e funcionando, vamos pular direto para como chamá-lo do Hibernate.
3. Chame um procedimento armazenado com Hibernate
A partir do Hibernate 3, temos a possibilidade de usar instruções SQL brutas, incluindo procedimentos armazenados para consultar um banco de dados.
Nesta seção, vamos percorrer um exemplo aparentemente básico que ilustrará como chamar o procedimentoGetAllFoos() usando o Hibernate.
3.1. Configuração
Antes de começarmos a escrever o código que pode ser executado, precisamos ter configurado o Hibernate em nosso projeto.
E, claro, para tudo isso - as dependências do Maven, a configuração do MySQL, a configuração do Hibernate e a instanciação deSessionFactory - você pode verificar oHibernate article.
3.2. Chame um procedimento armazenado usando o métodoCreateNativeSQL
O Hibernate permite expressar consultas no formatonative SQL diretamente. Portanto, podemos criar diretamente uma consulta SQL nativa e usar a instruçãoCALL para chamar o procedimento armazenadogetAllFoos():
Query query = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
List allFoos = query.list();
A consulta acima retorna uma lista onde cada elemento é umFoo object.
Usamos o métodoaddEntity() para obter objetos de entidade da consultaSQL nativa, caso contrário, umClassCastException será lançado sempre que um procedimento armazenado retornar um valor não bruto.
3.3. Chame um procedimento armazenado usando@NamedNativeQueries
Outra maneira de chamar um procedimento armazenado é usar a anotação@NamedNativeQueries.
@NamedNativeQueries é usado para especificar uma matriz de consultas nomeadasSQL nativasscoped to the persistence unit:
@NamedNativeQueries({
@NamedNativeQuery(
name = "callGetAllFoos",
query = "CALL GetAllFoos()",
resultClass = Foo.class)
})
@Entity
public class Foo implements Serializable {
// Model definition
}
Cada consulta nomeada tem obviamente um atributoname, oSQL query real eresultClass que se refere à entidade mapeadaFoo.
Query query = session.getNamedQuery("callGetAllFoos");
List allFoos = query.list();
O atributoresultClass desempenha a mesma função que o métodoaddEntity() em nosso exemplo anterior.
Ambas as abordagens podem ser usadas de forma intercambiável, pois não há diferenças reais entre as duas quando se trata de desempenho ou produtividade.
3.4. Chame um procedimento armazenado usando@NamedStoredProcedureQuery
Se você estiver usandoJPA 2.1e a implementaçãoHibernate deEntityManagerFactoryeEntityManager.
A anotação@NamedStoredProcedureQuery pode ser usada para declarar um procedimento armazenado:
@NamedStoredProcedureQuery(
name="GetAllFoos",
procedureName="GetAllFoos",
resultClasses = { Foo.class }
)
@Entity
public class Foo implements Serializable {
// Model Definition
}
Para chamar nossa consulta de procedimento armazenado nomeado, precisamos instanciar umEntityManager,e chamar o métodocreateNamedStoredProcedureQuery() para criar o procedimento:
StoredProcedureQuery spQuery =
entityManager.createNamedStoredProcedureQuery("getAllFoos");
Podemos obter diretamente a lista de entidadesFoo chamando o métodoexecute() no objetoStoredProcedureQuery.
4. Procedimentos armazenados com parâmetros
Quase todos os nossos procedimentos armazenados exigirão parâmetros. Nesta seção, mostraremos como chamar um procedimento armazenado com parâmetros deHibernate.
Vamos criar um procedimento armazenadogetFoosByName() emMySQL.
Este procedimento retorna uma lista de objetosFoo onde o atributo name corresponde ao parâmetrofooName:
DELIMITER //
CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT * FROM foo WHERE name = fooName;
END //
DELIMITER;
Para chamar o procedimentoGetFoosByName(), usaremos parâmetros nomeados:
Query query = session.createSQLQuery("CALL GetFoosByName(:fooName)")
.addEntity(Foo.class)
.setParameter("fooName","New Foo");
Da mesma forma, o parâmetro nomeado:fooName pode ser usado com a anotação@NamedNativeQuery:
@NamedNativeQuery(
name = "callGetFoosByName",
query = "CALL GetFoosByName(:fooName)",
resultClass = Foo.class
)
A consulta nomeada seria chamada da seguinte maneira:
Query query = session.getNamedQuery("callGetFoosByName")
.setParameter("fooName","New Foo");
Ao usar a anotação@NamedStoredProcedureQuery, podemos especificar parâmetros usando o@StoredProcedureParameter annotation:
@NamedStoredProcedureQuery(
name="GetFoosByName",
procedureName="GetFoosByName",
resultClasses = { Foo.class },
parameters={
@StoredProcedureParameter(name="fooName", type=String.class, mode=ParameterMode.IN)
}
)
Podemos usar o métodoregisterStoredProcedureParameter() para chamar nosso procedimento armazenado com o parâmetrofooName:
StoredProcedureQuery spQuery = entityManager.
createNamedStoredProcedureQuery("GetFoosByName")
.registerStoredProcedureParameter(
"New Foo",
String.class ,
ParameterMode.IN
);
5. Conclusão
Este artigo demonstrouhow to use Hibernate to call a stored procedure in a MySQL database usando diferentes abordagens.
Vale ressaltar quenot all RDBMS support stored procedures.
Você pode verificar os exemplos fornecidos neste artigo no linkGitHub project.