Este artigo descreve o método de operação em lote de hibernato. Compartilhe -o para sua referência, como segue:
Processamento de lote de hibernação
O Hibernate opera completamente o banco de dados de maneira orientada a objetos. Quando um objeto persistente é operado de maneira orientada a objetos no programa, ele será convertido automaticamente em uma operação no banco de dados. Por exemplo, ao ligar para o método Delete () de Sessão () para excluir um objeto persistente, o Hibernate será responsável por excluir os registros de dados correspondentes; Ao executar o método definido do objeto persistente, o Hibernate se converterá automaticamente ao método de atualização correspondente e modificará os registros correspondentes do banco de dados.
A questão é se 100.000 registros precisam ser atualizados ao mesmo tempo, você precisa carregar 100.000 registros um por um e, em seguida, chamar o método definido por sua vez - isso não é apenas complicado, mas também o desempenho do acesso a dados é muito ruim. Para este cenário de processamento em lote, o Hibernate fornece uma solução de processamento em lote. A seguir, introduz como enfrentar esta situação de processamento em lote de três aspectos: inserção em lote, atualização em lote e exclusão de lote.
1 Inserção de lote
Se você precisar inserir 100.000 registros no banco de dados, o Hibernate geralmente pode usar o seguinte:
Sessão session = sessionFactory.opensssion (); transação tx = session.begIntransaction (); para (int i = 0; i <100000; i ++) {user u = novo usuário (......); session.Save (cliente);} tx.Commit (); session.close ();Mas, como esse programa é executado, ele sempre falhará em algum momento e uma OrofMemoryException é lançada. Isso ocorre porque a sessão do Hibernate possui um cache de nível 1 exigido e todas as instâncias do usuário serão armazenadas em cache na área de cache no nível da sessão.
Para resolver esse problema, existe uma idéia muito simples: atualize regularmente os dados em cache pela sessão no banco de dados, em vez de sempre cache -os no nível da sessão. Você pode considerar projetar um acumulador, que aumenta em 1 para cada instância do usuário salva. Determine se os dados no cache da sessão precisam ser liberados no banco de dados com base no valor do acumulador.
Aqui está um trecho de código que adiciona 100.000 instâncias de usuário:
private void testUser () lança Exceção {// Abra sessão sessão sessão = hibernateutil.currentSession (); // Iniciar transação de transação TX = session.BegIntransaction (); // loop 100 000 vezes e insira 100 000 registros para (int i = 0; i <1000000; i ++) {// Crie a instância do usuário Usuário u1 = new User (); u1.setName ("xxxxx" + i); u1.setage (i); U1.setNationality ("China"); // cache a instância do usuário session.save (U1); // Sempre que o acumulador é um múltiplo de 20, libere os dados na sessão no banco de dados e limpe o cache da sessão se (i % 20 == 0) {session.flush (); session.clear (); tx.Commit (); tx = session.BegIntransaction (); }} // Confirme transação tx.Commit (); // Fechar transação HibernateUtil.Clossession ();}No código acima, quando i%20 == 0, os dados em cache na sessão são gravados manualmente no banco de dados e a transação é enviada manualmente. Se a transação não for enviada, os dados ainda serão armazenados em cache no escritório de transações - ele não entrou no banco de dados, o que também causará uma exceção do estouro de memória.
Este é o processamento do cache no nível da sessão, e o cache secundário do SessionFactory também deve ser desligado na configuração a seguir.
hibernate.cache.use_second_level_cache false
Nota: Além de limpar manualmente o cache no nível da sessão, é melhor desativar o cache secundário de nível de sessão. Caso contrário, mesmo que o cache no nível da sessão seja limpo manualmente, uma exceção poderá ser lançada porque ainda existe um cache no nível da sessão.
2 atualizações em lote
O método descrito acima também é adequado para dados de atualização em lote. Se você precisar retornar várias linhas de dados, poderá usar o método scroll () para fazer uso total das vantagens de desempenho trazidas por cursores do lado do servidor. Aqui está um trecho de código para atualizações de lote:
private void testUser () lança Exceção {// Abra sessão sessão sessão = hibernateutil.currentSession (); // Inicie a transação de transação TX = session.BegIntransaction (); // consulta todos os registros na tabela de usuários scrollableResults usuários = session.createQuery ("do usuário") .setcachemode (cachemode.ignore) .scroll (scrollmode.forward_only); int conting = 0; // transação Todos os registros na tabela de usuários while (users.next ()) {user u = (user) users.get (0); u.setName ("novo nome de usuário" + contagem); // Quando a contagem é um múltiplo de 20, libere o resultado atualizado da sessão para o banco de dados se (++ contagem % 20 == 0) {session.flush (); session.clear (); }} tx.commit (); Hibernateutil.closhessession ();} Dessa forma, embora as atualizações de lote possam ser realizadas, o efeito é muito ruim. A eficiência da execução não é alta e a consulta de dados é necessária primeiro e, em seguida, a atualização de dados é executada. Esta atualização será uma atualização em linha a linha, ou seja, sempre que uma linha de registros é atualizada, uma instrução de atualização precisa ser executada e o desempenho é muito baixo.
Para evitar isso, o Hibernate fornece uma sintaxe HQL semelhante ao SQL para atualizações de lote e exclusão de lote.
3 Atualização/exclusão em lote no estilo SQL
As instruções HQL fornecidas pelo Hibernate também suportam a atualização do lote e excluem a sintaxe.
O formato de sintaxe das declarações de atualização e exclusão de lote é o seguinte:
Atualização | Excluir? ClassName [Where Where_conditions]
Há quatro pontos que vale a pena notar sobre o formato de sintaxe acima:
● Na cláusula de From, a palavra -chave de From é opcional. Ou seja, você não pode escrever de palavras -chave.
● Pode haver apenas um nome de classe na cláusula de From, e o nome da classe não pode ter um alias.
● Você não pode usar conexões em declarações HQL em lote, nem explícitas nem implícitas. Mas as subconhas podem ser usadas na cláusula onde.
● Toda a cláusula onde é opcional.
Supondo que você precise alterar o atributo de nome da instância da classe de usuário, você pode usar o seguinte snippet de código:
private void testUser () lança Exceção {// Abra sessão sessão sessão = hibernateutil.currentSession (); // Iniciar transação de transação TX = session.BegIntransaction (); // Defina a atualização do lote HQL String string hQLupdate = "Atualizar nome do conjunto de usuários =: newName"; // Execute update int updateEntities = session.createquery (hqlupdate) .SetString ("newName", "new Name") .executeUpdate (); // Comprometer transação tx.commit (); Hibernateutil.closhessession ();}Como pode ser visto no código acima, essa sintaxe é muito semelhante à sintaxe ExecuteUpdate da estatição preparada. De fato, esta atualização em lote do HQL está emprestando diretamente a declaração de atualização da sintaxe SQL.
Nota: Ao usar esta sintaxe de atualização em lote, geralmente você só precisa executar a instrução SQL Atualizar uma vez para concluir todas as atualizações que atendem aos registros condicionais. Mas também pode ser necessário executar várias declarações de atualização, porque existem casos especiais, como mapeamento de herança, como uma instância de pessoa, que possui uma instância de subclasse do cliente. Quando o lote atualiza as instâncias da pessoa, a instância do cliente também precisa ser atualizada. Se você usar a estratégia de mapeamento de sub-esclasse ou subclasse união, as instâncias de pessoa e clientes são salvas em diferentes tabelas, para que várias declarações de atualização possam ser necessárias.
Execute um HQL Excluir e use o método query.executeUpdate (). A seguir, é apresentado um trecho de código que exclui todos os registros acima de uma só vez:
private void testUser () lança Exceção {// Abra a sessão session Sessão = HibernateUtil.CurrentSession (); // Iniciar transação de transação TX = session.BegIntransaction (); // Defina a exclusão de lote HQL String string hqlupdate = "excluir usuário"; // Execute a deleção em lote int updateEntities = session.CreateQuery (HQLUPDATE) .EXECUTEUPDATE (); // Comprometer transação tx.commit (); // Fechar a sessão hibernateutil.clossession ();}Retorna um valor inteiro pelo método query.executeUpdate (), que é o número de registros afetados por esta operação. De fato, as operações subjacentes da Hibernate são realizadas através do JDBC. Portanto, se houver lotes de atualização ou exclusão de operações convertidas em múltiplas instruções de atualização ou exclusão, o método retorna o número de registros afetados pela última instrução SQL.
Espero que a descrição deste artigo seja útil para a programação Java de todos com base na estrutura do Hibernate.