Quantcast
Viewing all articles
Browse latest Browse all 759

JPA / Hibernate executa Insert seguido de Update para um mesmo registro novo

@danieldestro escreveu:

Estou tendo um problema com JPA / Hibernate onde ele está executando um INSERT seguido de um UPDATE para um novo registro que ele persiste.

Quero eliminar a execução do UPDATE, pois não faz sentido nenhum ele executar este segundo comando, pois não estou explicitamente fazendo isso. Alguma ideia do que pode causar essa redundância?

O modelo de entidade é assim (sem entrar no mérito do design):

PriceSummary [1] --> [N] ServicePriceSummary [1] --> [N] ServicePriceBreakdown [1] --> [N] MonthBreakdown

Devido a uma lógica de negócio particular, pode chegar a 10.000 ou 20.000 (sim 20 mil) registros de MonthBreakdown que são criados nos cálculos para uma grande proposta.

Fazendo um profiling da nossa aplicação, este é um grande gargalo, onde as operações do MonthBreakdown de INSERT e UPDATE, juntas, representam mais de 90% do processamento.

Se conseguir eliminar o UPDATE em já reduz em quase 50% o tempo de processamento.

Meu código (resumido) é, basicamente, o seguinte:

@Service
@Transactional
public class PricingService {

    /** Método chamado para realizar a transação. */
    public PricingContext calculate(Integer id) {
        Proposal proposal = proposalRepository.findOne(id);
        
		PriceSummary summary = new PriceSummary(proposal);
		PricingContext context = new PricingContext(summary);
		
		List<Service> services = serviceRepository.findByProposalId(id);
		services.forEach(service -> calculate(service, context));
		
		priceSummaryRepository.saveAndFlush(summary); // JpaRepository interface
		
		return context;
    }
	
	public void calculate(Service service, PricingContext context) {
	    List<Rates> rates = ratesService.findRatesForProposal(context.getProposal()); // do some JPA queries and return data
		
		// faz uns calculos muito loucos aqui e atualiza PricingSummary em context
	}
}

Entidade PriceSummary:

@Entity
@Table(name="price_summary")
public class PriceSummary {

    @Id @Column(name = "id")
    private Integer id;

    @Column(name = "lock_version")
    private Integer lockVersion;

    @Column(name = "price")
    private BigDecimal price;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "priceSummary", orphanRemoval = true)
    private final List<ServicePriceSummary> servicePriceSummaries = new ArrayList<>();
	
	// getters & setters
}

Entidade ServicePriceSummary:

@Entity
@Table(name="srv_price_summary")
public class ServicePriceSummary {

    @Id @Column(name = "id")
    private Integer id;

    @ManyToOne @JoinColumn(name = "price_summary_id")
    private PriceSummary priceSummary;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "serviceOfferingPriceSummary", orphanRemoval = true)
	private final List<ServicePriceBreakdown> servicePriceBreakdowns = new ArrayList<>();
	
	// getters & setters
}

Entidade ServicePriceBreakdown:

@Entity
@Table(name="srv_price_breakdown")
public class ServicePriceBreakdown {

    @Id @Column(name = "id")
    private Integer id;

    @ManyToOne @JoinColumn(name = "srv_price_summary_id")
    private ServicePriceSummary servicePriceSummary;
	
	@Column(name = "country_code")
	private String countryCode;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "servicePriceBreakdown", orphanRemoval = true)
	private final List<MonthBreakdown> monthBreakdowns = new ArrayList<>();
	
	// getters & setters
}

Entidade MonthBreakdown:

@Entity
@Table(name="month_breakdown")
public class MonthBreakdown {

    @Id @Column(name = "id")
    private Integer id;

    @ManyToOne @JoinColumn(name = "srv_price_breakdown_id")
    private ServicePriceBreakdown servicePriceBreakdown;
	
	@Column(name = "month_number")
	private Integer month;
	
	@Column(name = "cost")
	private BigDecimal cost;
	
	// getters & setters
}

Curiosamente, se olhar o relatório do profiling do JProfiler, parece que ele executa o INSERT e depois o UPDATE quando se adiciona o registro em uma lista de um entidade. Porém no log SQL do Hibernate ele primeiro lista todos os INSERT e em seguida todos os UPDATE.

Outra estratégia foi configurar o Batch Size do Hibernate. Com isso tivemos algum ganho (20 a 40% em alguns casos), mas ainda não resolveu o problema.

Uma outra estratégia que pensamos foi remover a configuração de "cascade = CascadeType.ALL" da classe ServicePriceBreakdown no atributo monthBreakdowns e não deixar o Hibernate executar os INSERTS para o MonthBreakdown. Então, após salvar os objetos do grafo, reuno uma lista dos MonthBreakdown e explicitamente salvo, visando evita o UPDATE e melhorar execução em batch. Faz sentido?

Estamos usando OpenJDK 1.8, Spring Boot 1.3.1, Tomcat 7.

Mensagens: 1

Participantes: 1

Ler tópico completo


Viewing all articles
Browse latest Browse all 759

Trending Articles


Long Distance Relationship Tagalog Love Quotes


Pokemon para colorear


Sapos para colorear


Maganda Quotes – tagalog Quotes – Inggit Quotes


“Tado” Jimenez Quotes Collections Online


5 Tagalog Relationship Rules


Hugot Lines 2020 Patama : ML Edition


Re:Mutton Pies (lleechef)


Vimeo 10.7.0 by Vimeo.com, Inc.


Vimeo 10.7.1 by Vimeo.com, Inc.


FORECLOSURE OF REAL ESTATE MORTGAGE


Girasoles para colorear


tagalog love Quotes – Tiwala Quotes


OFW quotes : Pinoy Tagalog Quotes


Mga Patama sa mga Nagmamahal the Best Tagalog love quotes for you


Top 10 Best Tagalog Friendship Quotes and Sayings | mrbolero


“BAHAY KUBO HUGOT”


RE: Mutton Pies (frankie241)


EASY COME, EASY GO


HOY PANGIT, MAGBAYAD KA!



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>