Faz insert e depois o update da mesmas tabelas envolvidas

Analisando o log

Quando mando inserir, ele faz o insert nas tabelas OK e depois faz o Update das mesmas, o que não deveria.

Hibernate: insert into tab_empresa (ts_movimentacao, ip_movimentacao, cd_login_movimentacao, tp_operacao, ts_cadastro, st_registro, nr_versao, st_situacao, ds_celular_responsavel, ds_cnpj, ds_email_empresa, ds_email_responsavel, ds_nome, ds_nome_responsavel, ds_telefone_empresa, ds_telefone_responsavel, pk_empresa) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2020-07-11 16:09:35.825 DEBUG 54316 --- [  XNIO-1 task-1] org.hibernate.SQL                        : insert into tab_empresa_marketplaces (ts_movimentacao, ip_movimentacao, cd_login_movimentacao, tp_operacao, ts_cadastro, st_registro, nr_versao, st_situacao, fk_empresa, fk_marketplaces, nr_porcentagem, pk_empresa_marketplaces) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into tab_empresa_marketplaces (ts_movimentacao, ip_movimentacao, cd_login_movimentacao, tp_operacao, ts_cadastro, st_registro, nr_versao, st_situacao, fk_empresa, fk_marketplaces, nr_porcentagem, pk_empresa_marketplaces) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2020-07-11 16:09:35.832 DEBUG 54316 --- [  XNIO-1 task-1] org.hibernate.SQL                        : insert into tab_empresa_marketplaces (ts_movimentacao, ip_movimentacao, cd_login_movimentacao, tp_operacao, ts_cadastro, st_registro, nr_versao, st_situacao, fk_empresa, fk_marketplaces, nr_porcentagem, pk_empresa_marketplaces) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into tab_empresa_marketplaces (ts_movimentacao, ip_movimentacao, cd_login_movimentacao, tp_operacao, ts_cadastro, st_registro, nr_versao, st_situacao, fk_empresa, fk_marketplaces, nr_porcentagem, pk_empresa_marketplaces) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2020-07-11 16:09:35.834 DEBUG 54316 --- [  XNIO-1 task-1] org.hibernate.SQL                        : update tab_empresa set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, ds_celular_responsavel=?, ds_cnpj=?, ds_email_empresa=?, ds_email_responsavel=?, ds_nome=?, ds_nome_responsavel=?, ds_telefone_empresa=?, ds_telefone_responsavel=? where pk_empresa=? and nr_versao=?
Hibernate: update tab_empresa set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, ds_celular_responsavel=?, ds_cnpj=?, ds_email_empresa=?, ds_email_responsavel=?, ds_nome=?, ds_nome_responsavel=?, ds_telefone_empresa=?, ds_telefone_responsavel=? where pk_empresa=? and nr_versao=?
2020-07-11 16:09:35.843 DEBUG 54316 --- [  XNIO-1 task-1] org.hibernate.SQL                        : update tab_empresa_marketplaces set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, fk_empresa=?, fk_marketplaces=?, nr_porcentagem=? where pk_empresa_marketplaces=? and nr_versao=?
Hibernate: update tab_empresa_marketplaces set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, fk_empresa=?, fk_marketplaces=?, nr_porcentagem=? where pk_empresa_marketplaces=? and nr_versao=?
2020-07-11 16:09:35.847 DEBUG 54316 --- [  XNIO-1 task-1] org.hibernate.SQL                        : update tab_empresa_marketplaces set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, fk_empresa=?, fk_marketplaces=?, nr_porcentagem=? where pk_empresa_marketplaces=? and nr_versao=?
Hibernate: update tab_empresa_marketplaces set ts_movimentacao=?, ip_movimentacao=?, cd_login_movimentacao=?, tp_operacao=?, ts_cadastro=?, st_registro=?, nr_versao=?, st_situacao=?, fk_empresa=?, fk_marketplaces=?, nr_porcentagem=? where pk_empresa_marketplaces=? and nr_versao=?

Código está assim:

Empresa

package br.com.ghnetsoft.ctrmarketplacestrategy.domain.empresa;

import static lombok.AccessLevel.PROTECTED;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.envers.AuditOverride;
import org.hibernate.envers.Audited;

import br.com.ghnetsoft.ctrmarketplacestrategy.domain.pai.Principal;
import br.com.ghnetsoft.ctrmarketplacestrategy.domain.pai.auditoria.AuditableBase;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * Classe do banco de dados de empresa
 * 
 * @author Guilherme C Lopes
 */
@Entity
@Setter
@Getter
@Builder
@Table(name = "TAB_EMPRESA", uniqueConstraints = {
		@UniqueConstraint(columnNames = { "DS_CNPJ" }, name = "U1_TAB_EMPRESA") }, indexes = {
				@Index(columnList = "ST_REGISTRO", name = "I1_TAB_EMPRESA"),
				@Index(columnList = "DS_CNPJ", name = "I2_TAB_EMPRESA") })
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
@Audited
@AuditOverride(forClass = AuditableBase.class)
public class Empresa extends Principal {

	private static final long serialVersionUID = 3629606672280321002L;

	@Id
	@Column(name = "PK_EMPRESA", updatable = false, unique = true, nullable = false)
	@GeneratedValue(generator = "UUID")
	@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
	private String id;
	@Column(name = "DS_NOME", nullable = false)
	private String nome;
	@Column(name = "DS_CNPJ", length = 14, nullable = false)
	private String cnpj;
	@Column(name = "DS_TELEFONE_EMPRESA", length = 10)
	private String telefoneEmpresa;
	@Column(name = "DS_EMAIL_EMPRESA", nullable = false)
	private String emailEmpresa;
	@Column(name = "DS_NOME_RESPONSAVEL", nullable = false)
	private String nomeResponsavel;
	@Column(name = "DS_TELEFONE_RESPONSAVEL", length = 10)
	private String telefoneResponsavel;
	@Column(name = "DS_CELULAR_RESPONSAVEL", length = 11)
	private String celularResponsavel;
	@Column(name = "DS_EMAIL_RESPONSAVEL", nullable = false)
	private String emailResponsavel;
}

EmpresaMarketPlaces

package br.com.ghnetsoft.ctrmarketplacestrategy.domain.empresamarketplaces;

import static lombok.AccessLevel.PROTECTED;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;
import static org.hibernate.envers.RelationTargetAuditMode.NOT_AUDITED;

import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.envers.AuditOverride;
import org.hibernate.envers.Audited;

import br.com.ghnetsoft.ctrmarketplacestrategy.domain.empresa.Empresa;
import br.com.ghnetsoft.ctrmarketplacestrategy.domain.marketplaces.MarketPlaces;
import br.com.ghnetsoft.ctrmarketplacestrategy.domain.pai.Principal;
import br.com.ghnetsoft.ctrmarketplacestrategy.domain.pai.auditoria.AuditableBase;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * Classe do banco de dados de Market Places por empresa
 * 
 * @author Guilherme C Lopes
 */
@Entity
@Setter
@Getter
@Builder
@Table(name = "TAB_EMPRESA_MARKETPLACES", uniqueConstraints = { @UniqueConstraint(columnNames = { "FK_EMPRESA",
		"FK_MARKETPLACES" }, name = "U1_TAB_MARKETPLACES_EMPRESA") }, indexes = {
				@Index(columnList = "ST_REGISTRO", name = "I1_TAB_MARKETPLACES_EMPRESA"),
				@Index(columnList = "FK_EMPRESA", name = "I2_TAB_MARKETPLACES_EMPRESA"),
				@Index(columnList = "FK_MARKETPLACES", name = "I3_TAB_MARKETPLACES_EMPRESA") })
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
@Audited
@AuditOverride(forClass = AuditableBase.class)
public class EmpresaMarketPlaces extends Principal {

	private static final long serialVersionUID = -4423665309182124888L;

	@Id
	@Column(name = "PK_EMPRESA_MARKETPLACES", updatable = false, unique = true, nullable = false)
	@GeneratedValue(generator = "UUID")
	@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
	private String id;
	@Audited(targetAuditMode = NOT_AUDITED)
	@ManyToOne(targetEntity = Empresa.class)
	@JoinColumn(name = "FK_EMPRESA", nullable = false, foreignKey = @ForeignKey(name = "FK_EMPRESA"))
	private Empresa empresa;
	@Audited(targetAuditMode = NOT_AUDITED)
	@ManyToOne(targetEntity = MarketPlaces.class)
	@JoinColumn(name = "FK_MARKETPLACES", nullable = false, foreignKey = @ForeignKey(name = "FK_MARKETPLACES"))
	private MarketPlaces marketPlaces;
	@Column(name = "NR_PORCENTAGEM", nullable = false, length = 25, precision = 2)
	private BigDecimal porcentagem;
}

Salvar está salvando empresa e depois EmpresaMarketPlaces, dentro do serviço de Empresa assim:

/**
	 * Metodo que salva uma Empresa
	 * 
	 * @param empresa
	 * @param empresasMarketsPlacesIncluir
	 * @param empresasMarketsPlacesExcluir
	 * @return
	 */
	private EmpresaDTO salvar(Empresa empresa,
			Collection<EmpresaMarketPlacesIncluirAlterarDTO> empresasMarketsPlacesIncluir,
			Collection<EmpresaMarketPlacesIncluirAlterarDTO> empresasMarketsPlacesExcluir) {
		log.info("Metodo que salva uma Empresa");
		aplicacaoAuditoria(empresa);
		empresa = repository.save(empresa);
		Collection<EmpresaMarketPlaces> empresasMarketsPlaces = empresaMarketPlacesService
				.incluirPorEmpresa(empresasMarketsPlacesIncluir, empresa);
		return new EmpresaDTO(empresa, empresasMarketsPlaces);
	}

Pois no log, nunca tem um INSERT

O que pode ser ?

Esse repository é uma instância de EntityManager?
Caso afirmativo, utilize o método persist ao invés de save.

1 curtida
@Repository
interface EmpresaRepository extends JpaRepository<Empresa, String> {

O que o método incluirPorEmpresa faz? Manda o código dele.

1 curtida
@Transactional
	@Override
	public Collection<EmpresaMarketPlaces> incluirPorEmpresa(
			Collection<EmpresaMarketPlacesIncluirAlterarDTO> empresasMarketsPlacesIncluir, Empresa empresa) {
		log.info("Metodo que inclui EmpresaMarketPlaces pelo formulario de empresa");
		Collection<EmpresaMarketPlaces> empresasMarketsPlaces = new ArrayList<>();
		if (empresasMarketsPlacesIncluir != null && !empresasMarketsPlacesIncluir.isEmpty()) {
			for (EmpresaMarketPlacesIncluirAlterarDTO emp : empresasMarketsPlacesIncluir) {
				log.info("MarketPlaces com id: " + emp.getIdMarketPlaces());
				EmpresaMarketPlaces empresaMarketPlaces = EmpresaMarketPlaces.builder().build();
				empresaMarketPlacesPreencher.preencherPorEmpresa(empresaMarketPlaces, emp.getIdMarketPlaces(),
						emp.getPorcentagem(), empresa);
				aplicacaoAuditoria(empresaMarketPlaces);
				empresasMarketsPlaces.add(empresaMarketPlaces);
			}
			empresasMarketsPlaces = repository.saveAll(empresasMarketsPlaces);
		}
		return empresasMarketsPlaces;
	}

Para testes, comente o @Audited e veja se esse update ainda é executado?

1 curtida

E entidades normais que não tenho outra envolvida, ele cadastra normal.

Tenho esta classe também

package br.com.ghnetsoft.ctrmarketplacestrategy.domain.pai.auditoria;

import static br.com.ghnetsoft.ctrmarketplacestrategy.enuns.OperacacoBancoLogEnum.ALTERACAO;
import static br.com.ghnetsoft.ctrmarketplacestrategy.enuns.OperacacoBancoLogEnum.INCLUSAO;
import static lombok.AccessLevel.PROTECTED;

import java.util.Date;

import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.apachecommons.CommonsLog;

/**
 * Classe de Auditoria de banco de dados
 * 
 * @author Guilherme C Lopes
 */
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@CommonsLog
class Auditor {

	private AuditMetadata auditData = new AuditMetadata();

	/**
	 * Audita a inclusao
	 * 
	 * @param entidade
	 */
	@PrePersist
	public void auditaInclusao(AuditableBase entidade) {
		auditData.setTipoOperacao(INCLUSAO);
		audita(entidade);
	}

	/**
	 * Audita a alteracao
	 * 
	 * @param entidade
	 */
	@PreUpdate
	public void auditaAlteracao(AuditableBase entidade) {
		auditData.setTipoOperacao(ALTERACAO);
		audita(entidade);
	}

	/**
	 * Preenche a aufitoria da entidade para salvar
	 * 
	 * @param entidade
	 */
	private void audita(AuditableBase entidade) {
		auditData.setDataHoraMovimentacao(new Date());
		auditData.setIpMovimentacao(entidade.getMetadadoAuditoria().getIpMovimentacao());
		auditData.setLoginMovimentacao(entidade.getMetadadoAuditoria().getLoginMovimentacao());
		log.info(getClass().getName() + ": " + entidade.getClass().getName());
		entidade.setMetadadoAuditoria(auditData);
	}
}

Eu acho que a questão é o save em uma transação somente. porque neste caso ele exeuta o método auditaInclusao e auditaAlteracao.

Se eu tenho uma classe que quando salvo só uma, na inserção ela não executa auditaAlteracao.

Alguma novidade ?

Alguma novidade ?

Faz o insert/update sob seu controle com jdbctemplate. Além de ser mais leve, não vai ficar uma semana lidando com esses e outros enigmas do jpa/hibernate.

Outra coisa só como dica, em empresas sérias difícilmente é aceito o sistema auditar a si mesmo. Ideal é ser por trigger em um schema com acesso mais restrito. Claro que se nao for algo crítico, pode fazer de qualquer forma.

1 curtida

Colocar logs em outro schema até acho melhor. E vou fazer isso. Boa idéia.

O envers já faz o papel do envers. Acho que já ouvi algo aqui sobre isso. Já trabalhei projetos em empresas grandes que utilizam o envers para isso, mas realmente em schema diferentes.

Se esse “envers” for da própria aplicação o programador pode burlar a auditoria.

1 curtida

Entendi o que vc quis dizer