Ambiente de Desenvolvimento deste artigo: Spring-Boot: 2.0.3.Release + Java1.8
Por que fazer
Deleção suave: isto é, nenhuma operação de exclusão real é realizada. Devido à existência de ligação (chaves estrangeiras) entre nossas entidades, a exclusão de alguns dados levará a outros dados incompletos. Por exemplo, o professor na aula de computador 1801 é Zhang San. Neste momento, se excluirmos Zhang San, então, quando consultarmos a classe de computador 1801, já que Zhang San não existe mais, relataremos o EnterityNotFound Error. Obviamente, em um banco de dados com restrições de chave estrangeira, se Zhang San for um professor na classe 1801, excluiremos diretamente Zhang San e relataremos uma exceção de ligação. Em outras palavras, o comportamento de excluir diretamente o Zhang San não pode ser executado.
Mas, às vezes, temos a necessidade de excluí -lo. Por exemplo, um funcionário sai e então queremos excluir o funcionário no gerenciamento de funcionários. No entanto: o funcionário tem um histórico na tabela de dados. Por exemplo, registramos que a estrutura de dados do segundo semestre de 2017 foi Zhang Sanjiao. Então, devido à existência de restrições, será relatado um erro de ligação ao excluir Zhang San. Em outras palavras: o constrangimento de ser excluído, mas não pode ser excluído.
Isso usa a exclusão suave mencionada neste artigo. A chamada exclusão suave significa que eu realmente não excluo os dados na tabela de dados, mas, em vez disso, adicione uma marca ao registro se deve excluí-los.
O Spring JPA suporta a exclusão suave, podemos encontrar mais artigos com boa qualidade para resolver esse problema. As etapas gerais são: 1. Adicione @sqldElete ("Atualizar xxxx set deleted = 1 where id = ?")。2.加入@Where(clause = "deleted = false") . Mas esta solução não é perfeita. Especificamente manifestado em:
Vamos tomar Zhang San como professor na classe 1801 como exemplo.
Depois de adicionar a anotação, podemos de fato excluir com sucesso Zhang San. Após a operação de exclusão, verificamos a tabela de dados e o registro de Zhang San ainda está lá. Mas, neste momento, se fizermos all ou consulta page , receberemos um erro 500 EntiyNotFound . Isso ocorre porque durante toda a consulta, o JPA adiciona automaticamente os parâmetros de consulta no @Where . Devido a deleted = true dos dados associados, uma exceção de que a entidade associada não é encontrada.
Mas o fato é: embora a entidade seja excluída, ela ainda está lá e queremos aplicá -la à consulta da associação. Não é esperado que ele tenha uma exceção 500 EntiyNotFound .
A solução deste artigo implementa:
Solução
Implementação
inicialização
Crie três novas entidades: ClazzTest, Clazz, Teacher e crie uma nova entidade de classe abstrata BaseEntity . Onde ClazzTest é usado para demonstrar a exceção que ocorre ao usar @Where(clause = "deleted = false") .
pacote com.mengyunzhi.springbootsamplecode.softDelete.entity; importar javax.persistence.mappedsuperclass; @MapDSuperClasspublic Resumo Classe Baseentidade {Private Boolean Deleted = False; // setter e getter} pacote com.mengyunzhi.springbootsamplecode.softDelete.entity; importar org.hibernate.annotações.sqlDelete; importar javax.persistence.entity; import javax.persistence.GeneratedValue; import Javax.perrence.id; SET DELETED = 1 onde id =? ") Classe pública Klass estende a base de base {@id @generatedValue Private Long Id; nome de string privado; // setter e getter} @Entity @sqldElete (sql = "update` klass_test` set deleted = 1 where id =? ") @Where (cláusula =" deleted = false ") public class Klasstest estende a base {@id @GeneratedValue private Long id; Nome da sequência privada;} Reescreva Crudrepository
package com.mengyunzhi.springbootsamplecode.softdelete.core;import org.springframework.data.jpa.repository.Query;import org.springframework.data.repository.CrudRepository;import org.springframework.data.repository.NoRepositoryBean;import javax.Transaction.Transaction; importar java.util.optional;/*** Aplicar SOFT DELETE* padrão @where (cláusula = "Deleted = 0") causará uma exceção da objeto Notfound quando uma consulta associada é realizada dentro do hibernato* Redefinar a interface aqui* https://stackoverflow.com/questions/19323557/handling-Soft-deletes-with-spring-jpa/222202469 * @Author Mengyunzhi Desenvolvimento de software da HEBEI University of Technology */ @norepositoryBeanpublic SofteleTeTrepRudrepRudrePository T Technology */ @norepositório @Override @Transaction @Query ("Selecione e de #{ #entityName} e onde e.id =? 1 e e.Deleted = false") opcional <T> findById (id); @Override @Transaction padrão boolean existbyId (id id) {return findById (id) .ispresent (); } @Override @Transaction @Query ("Selecione e de #{ #entityName} e onde e.deleted = false") iterable <T> findAll (); @Override @Transaction @Query ("Selecione e de #{ #entityName} e onde e.id in? 1 e e.Deleted = false") iterable <T> findAllById (iterable <d> ids); @Override @Transaction @Query ("Selecione contagem (e) de #{ #entityName} e onde e.deleted = false") long count ();} Crie uma nova aula de armazém
Herdando o crudrepository da primavera.
/*** classe* @author panjie*/interface pública klassRepository estende SoftDeleteCrudrepository <Klass, long> {} interface pública klasstestrepository estende softdeletecrudrepository <klasstest, long> {} interface pública ProfessorRepository estende Crudrepository <Professor, Long> {} teste
pacote com.mengyunzhi.springbootsamplecode.softDelete.repository; importação com.mengyunzhi.springbootsamplecode.softDelete.entity.klass; import com.mengyunzhi.springbootsamplode.seflete.entity.mengyunzhi.springboetsamplode.SoftDeletesity.Meng. com.mengyunzhi.springbootsamplecode.softDelete.entity.teacher; importar org.assertj.core.api.assertions; importar org.junit.test; import org.junit.runner.runwith; import.lf4j.logger; org.springframework.beans.factory.annotation.autowired; importar org.springframework.boot.test.context.springboottest; import org.springframework.orm.jpa.jpaobjectReievAlFexception; importFramework.ormworkwork.estworksRertRerrTring.Tringwork.Tringwork.Stringwork.StringFramework.Tringwork.Stringwork.Jpa.jPaObjectReieValFexception; importação.SpringFringFringRework.Tringwork.StRingFringFramwork.Jpa.jPaObjectReievExtexcepth; java.util.list; importar java.util.optional;/** * @author panjie */@springboottest@runwith (springrunner.class) classe public ProfessorRepositoryTest {private Final Static Logger = LoggerFactory.GetLogger (ProfessorRpositórioTest.cl.; @Autowired KlassRepository KlassRepository; @AUTOWIRED KLASSTESTREPOSITEME KLASSTESTREPOSITEMENT; @AUTOWIREDEDENDEDREPOSITEMENTEPOSITION; @Test public void findById () {Logger.info ("Crie um novo professor com Klass e Klasstest"); Klass Klass = new Klass (); KlassRepository.Save (Klass); Klasstest Klasstest = new Klasstest (); klasstestrepository.save (Klasstest); Professor = novo professor (); professor.setklass (Klass); professor.setklasstest (Klasstest); ProfessorRepository.Save (professor); Logger.info ("Procure o professor, afirme que a entidade foi encontrada e nenhuma exceção ocorreu"); Opcional <Professor> ProfessorOptional = ProfessorRepository.findbyId (professor.getId ()); Assertions.assertThat (professorOption.get ()). IsNotNull (); Logger.info ("Exclua o Klass associado e, em seguida, procure a entidade do professor, afirme que a entidade foi encontrada, nenhuma exceção ocorreu. Afirme que ainda existe uma entidade Klass excluída na entidade do professor"); klassRepository.deletebyId (klass.getId ()); ProfessorOptional = ProfessorRepository.findbyId (professor.getId ()); Assertions.assertThat (professorOption.get ()). IsNotNull (); Assertions.assertThat (professionOption.get (). GetKlass (). GetId ()). IsEqualto (klass.getId ()); Logger.Info ("Procure a lista de professores, nenhuma exceção ocorreu. Afirme que existe um registro de entidade Klass excluído na entidade do professor"); Lista <PRESSION> professorlist = (List <Fora>) professorRepository.findall (); para (professor do professor1: professor) {assertions.assertThat (professor1.getklass (). getId ()). isEqualto (klass.getId ()); } Logger.info ("Exclua o Klasstest associado e, em seguida, procure a entidade do professor, afirme que o Klasstest excluído foi encontrado"); klasstestrepository.deletebyId (klasstest.getId ()); ProfessorOptional = ProfessorRepository.findbyId (professor.getId ()); Assertions.assertThat (professorOption.get ()). IsNotNull (); Assertions.assertThat (professorOption.get (). Getklasstest (). GetId ()). IsEqualto (klasstest.getId ()); Logger.Info ("Procure a lista de professores novamente, afirme que ocorrerá uma exceção (entidade não é capturada, encapsulada e lançada) exceção"); Boolean CatchException = false; tente {professorrepository.findall (); } catch (jpaobjectRevieValFailureException e) {CatchException = true; } Assertions.assertThat (CatchException) .istrue (); }} Resumir
Ao usar a anotação padrão @sqldelete e @where, os dados do JPA podem lidar bem com o método findbyId (), mas não consegue lidar bem com o método findall (). Aqui, implementamos o método de reescrever o método CrunRepository. Quando conduziremos consultas básicas, usamos nosso método personalizado para adicionar deleto = true. Quando o JPA realiza uma consulta de associação, pois não definimos a anotação @where, todos os dados serão consultados, evitando assim a exceção que ocorre às vezes quando a consulta do Foundall () é realizada.
Neste artigo, fornecemos apenas algum código de exemplo.
Se você precisar do código completo, clique em: https://github.com/mengyunzhi/springbootsamplecode/tree/master/softdelete.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.