Boa noite!
Estou com um tremendo problema com Oracle + Toplink. Nosso banco de dados é gigantesco e a tela mais utilizada tem muitos campos. A questão é que o sistema demora uma eternidade para abrir esta tela. Óbvio que pelo volume de dados, pois uma tela com dois campos ele abre em 3s, enquanto que nessa outra problemática demora cerca de 50s.
Alguém se arrisca a dizer o que pode fazer com que o Toplink ficar lento desse jeito?
Olá
É difícil dizer algo com tão pouco informação técnica.
Se são muitos dados, já tentou fazer paginação deles?
Verifique se a query gerada pelo toplink está com performance adequada através do explain plain.
Vamos lá… eis o persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="wserpPU" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
<properties>
<property name="toplink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="toplink.jdbc.url" value="jdbc:oracle:thin:@XXXXXX:1521:xe"/>
<property name="toplink.jdbc.user" value="XXXXX"/>
<property name="toplink.jdbc.password" value="XXXXXX"/>
<property name="toplink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>
O sistema se comunica com o banco de dados através de transações. Mais ou menos assim:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("wserpPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ClasseX objeto1 = new ClasseX();
// sequencia de alterações no objeto
em.merge(objeto1);
em.getTransaction().commit();
em.close();
Entretanto… existem situações específicas onde o sistema literalmente trava para conseguir rodar uma query:
if ((operacao.getFluxo().getTipoFluxo().getId().equals(TipoFluxo.TIPO_COMPRA) || operacao.getFluxo().getTipoFluxo().getId().equals(TipoFluxo.TIPO_DEVOLUCAO))
&& operacao.getFluxo().getDescricao().equals("Finalizada")) {
for (OperacaoItem item : operacao.getItens()) {
item.getSeriais().size();
for (Serial s : item.getSeriais()) {
if (!em.getTransaction().isActive()) {
em.getTransaction().begin();
}
s.setProduto(item.getProduto());
em.merge(s);
em.getTransaction().commit();
}
}
}
O código acima resulta numa porção de queries como esta, sempre seguido de um commit, pois se deixasse pra colocar o commit depois de inserir 5000 linhas, o Oracle iria dar lock em 5000 linhas e travar o sistema:
E aqui a classe Serial:
[code]@Entity
@Table(name = “SERIAL”)
public class Serial implements Serializable {
@Transient
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private static final long serialVersionUID = 1L;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// id
//
@Id
@SequenceGenerator(name = "SeqSerialId", sequenceName = "SEQ_SERIAL_ID", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SeqSerialId")
@Basic(optional = false)
@Column(name = "ID")
private Long id;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// numero
//
@Column(name = "NUMERO")
private String numero;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// partNumber
//
@Column(name = "PART_NUMBER")
private String partNumber;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// ean
//
@Column(name = "EAN")
private String ean;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// produto
//
@JoinColumn(name = "PRODUTO_ID", referencedColumnName = "ID")
//@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@ManyToOne
private Produto produto;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// itemCotacao
//
@JoinColumn(name = "ITEM_COTACAO_ID", referencedColumnName = "ID")
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private ItemCotacao itemCotacao;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// itemNotaFiscalEntrada
//
@JoinColumn(name = "NOTA_FISCAL_ENTRADA_ITEM_ID", referencedColumnName = "ID")
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private NotaFiscalEntradaItem itemNotaFiscalEntrada;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// operacaoItemEntrada
//
@JoinColumn(name = "OPERACAO_ITEM_ENTRADA_ID", referencedColumnName = "ID")
@ManyToOne
private OperacaoItem operacaoItemEntrada;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// operacaoItemSaida
//
@JoinColumn(name = "OPERACAO_ITEM_SAIDA_ID", referencedColumnName = "ID")
@ManyToOne
private OperacaoItem operacaoItemSaida;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// ordemProducao
//
@JoinColumn(name = "ORDEM_PRODUCAO_ID", referencedColumnName = "ID")
@ManyToOne
private OrdemProducao ordemProducao;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[/code]
Quando vejo os logs de performance do Oracle (ADDM), ele me diz que a recomendação é melhorar a SQL na aplicação, mas simplesmente não vejo mais como melhorar o processo, uma vez que esse trecho acima é um ponto crítico e extremamente necessário para o sistema, pois se trata do momento da gravação do número de série em um produto.
Sempre que o usuário precisa inserir seriais é um tormento (pra gente), pois a alegação dele é mais do que correta: “o sistema está travado!” e até hoje não conseguimos descobrir a real causa disso.
Apreciaria muito qualquer tipo de ajuda que possa me dar uma luz, pois estou a ponto de mandar eles socarem esse sistem lá onde o sol não bate, haha. :twisted:
Olá
Ali naquele for dentro de outro for tente pensar em uma forma pra usar query com joins ao invés dos métodos get.