Trigger e SP no Hiberante? Regras de dominio ? -> Hibernate

Bom… tenha uma duvida + ou - conceitual… o que é melhor ?? escrever regras de dominio so em java… utilizar os stored procedures ?? ou unir os 2 (confesso que não entendo bem como unir os 2) …

fora isso, como é possivel via hibernate utilizar stored procedures ?? tnks

Duvida atual… como definir os Listers pra uma entidade via annotations no Hibernate ??

Olá Lavieri,
seguinte, por experiência, tudo depende,

se seu sistema for legado e vc tiver a certeza que não mudará de BANCO DE DADOS até o fim da vida dele, etc. as STORED, etc não é uma má ideia. Mas… se for uma aplicação comercial, que trocará de banco a todo momento, etc, repense sobre isso, visto que STORED, etc muda de sintaxe, etc de banco para banco.

Espero ter ajudado.

Sandro Lemanski da Silva

[quote=Lavieri]Bom… tenha uma duvida + ou - conceitual… o que é melhor ?? escrever regras de dominio so em java… utilizar os stored procedures ?? ou unir os 2 (confesso que não entendo bem como unir os 2) …

fora isso, como é possivel via hibernate utilizar stored procedures ?? tnks[/quote]

Melhor para o quê e para quem ?
Para o desenvolvedor é melhor que tudo seja em java. Store procedures não são portáveis.

Para eficiencia SP são melhores.

Em tese vc deve usar um Application Server e não usar Store Procedures. Essa é amelhor maneira de manter tudo em java com a mesma performance ( ou quase) que as SP.

[quote=sergiotaborda][quote=Lavieri]Bom… tenha uma duvida + ou - conceitual… o que é melhor ?? escrever regras de dominio so em java… utilizar os stored procedures ?? ou unir os 2 (confesso que não entendo bem como unir os 2) …

fora isso, como é possivel via hibernate utilizar stored procedures ?? tnks[/quote]

Melhor para o quê e para quem ?
Para o desenvolvedor é melhor que tudo seja em java. Store procedures não são portáveis.

Para eficiencia SP são melhores.

Em tese vc deve usar um Application Server e não usar Store Procedures. Essa é amelhor maneira de manter tudo em java com a mesma performance ( ou quase) que as SP.[/quote]

Hmm… não sei bem o que vc kiz dizer com Application Server…

Se não for usar SP, como fazer uso de gatilhos em java ?? mais especificamente em Hibernate…

falo para a hora de persistencia claro, pq as vezes vc da um new Bean() … mais não necessariamente vai persistir esse bean, porem quando persiste, é interessante fazer os gatilhos…

Dando um exemplo…

No meu problema eu tenho Grupo de produtos, que são guardados em estoque, esses dados são armazenados em uma tabela “estoque_grupo” cada grupo consiste em um ID e uma DESCRICAO

tenho uma tabela de produtos EstoqueProduto, onde cada produto pertence a um grupo de produtos, os campos desta tabela são… ID, GRUPO_ID, DESCRICAO

tenho uma tabela, com a relação de estoque de cada filial, onde todo EstoqueProduto, tem obrigatoriamente um EstoqueProdutoLoja para cada loja…
Sendo assim… sempre que eu criar um novo produto, um gatilho precisa ser acionado, criado novos EstoqueProdutoLoja para cada uma das lojas… o mesmo ocorre quando eu crio uma loja… um gatilho é acionado, criando todos os EstoqueProdutoLoja, para cada um dos produtos, para essa minha nova loja…

Não sei como fazer isso pelo Hibernate =//

[quote=Lavieri][quote=sergiotaborda][quote=Lavieri]Bom… tenha uma duvida + ou - conceitual… o que é melhor ?? escrever regras de dominio so em java… utilizar os stored procedures ?? ou unir os 2 (confesso que não entendo bem como unir os 2) …

fora isso, como é possivel via hibernate utilizar stored procedures ?? tnks[/quote]

Melhor para o quê e para quem ?
Para o desenvolvedor é melhor que tudo seja em java. Store procedures não são portáveis.

Para eficiencia SP são melhores.

Em tese vc deve usar um Application Server e não usar Store Procedures. Essa é amelhor maneira de manter tudo em java com a mesma performance ( ou quase) que as SP.[/quote]

Hmm… não sei bem o que vc kiz dizer com Application Server…

Se não for usar SP, como fazer uso de gatilhos em java ?? mais especificamente em Hibernate…

falo para a hora de persistencia claro, pq as vezes vc da um new Bean() … mais não necessariamente vai persistir esse bean, porem quando persiste, é interessante fazer os gatilhos…[/quote]

Hibernate não é mágico.
Para ter capacidades de trigger vc precisa ter Repositorios que ativam esses triggers. Precisa usar o padrão Observer.

O Hibernate tem capacidades de Observer até onde sei. Vc pode amarrar as coisas para que o hibernate o avise de alterações e processar. Mas seria melhor que vc mesmo ativasses os triggers via repositorio. Bom, pelo menos se vc gosta de codigo bem organizado e automáticamente testável.

Por exemplo… um dos meus Caso de Uso é esse abaixo…

Quando eu adcionar 1 produto… ou quando eu adcionar 1 loja… é necessario que sejam criado os respectivos registros para LOJA <-> PRODUTO

[quote=sergiotaborda]

Hibernate não é mágico.
Para ter capacidades de trigger vc precisa ter Repositorios que ativam esses triggers. Precisa usar o padrão Observer.

O Hibernate tem capacidades de Observer até onde sei. Vc pode amarrar as coisas para que o hibernate o avise de alterações e processar. Mas seria melhor que vc mesmo ativasses os triggers via repositorio. Bom, pelo menos se vc gosta de codigo bem organizado e automáticamente testável.[/quote]

Aparentemente é magico sim =x … pelomenos quanto a isso…

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/event/package-summary.html

AutoFlushEventListener "Defines the contract for handling of session auto-flush events."" DeleteEventListener "Defines the contract for handling of deletion events generated from a session." DirtyCheckEventListener "Defines the contract for handling of session dirty-check events." EventSource EvictEventListener "Defines the contract for handling of evict events generated from a session." FlushEntityEventListener FlushEventListener "Defines the contract for handling of session flush events." Initializable "An event listener that requires access to mappings to initialize state at initialization time." InitializeCollectionEventListener "Defines the contract for handling of collection initialization events generated by a session." LoadEventListener "Defines the contract for handling of load events generated from a session." LockEventListener "Defines the contract for handling of lock events generated from a session." MergeEventListener "Defines the contract for handling of merge events generated from a session." PersistEventListener "Defines the contract for handling of create events generated from a session." PostDeleteEventListener "Called after deleting an item from the datastore" PostInsertEventListener "Called after insterting an item in the datastore" PostLoadEventListener "Occurs after an an entity instance is fully loaded." PostUpdateEventListener "Called after updating the datastore" PreDeleteEventListener "Called before deleting an item from the datastore" PreInsertEventListener "Called before inserting an item in the datastore" PreLoadEventListener "Called before injecting property values into a newly loaded entity instance." PreUpdateEventListener "Called before updating the datastore" RefreshEventListener "Defines the contract for handling of refresh events generated from a session." ReplicateEventListener "Defines the contract for handling of replicate events generated from a session." SaveOrUpdateEventListener "Defines the contract for handling of update events generated from a session"

la tem tudo que preciso… e tudo que uma Trigger faz… so preciso saber agora como injetar os Ouvintes ^^ … estou procurando na API o lugar certo

[quote=Lavieri][quote=sergiotaborda]

Hibernate não é mágico.
Para ter capacidades de trigger vc precisa ter Repositorios que ativam esses triggers. Precisa usar o padrão Observer.

O Hibernate tem capacidades de Observer até onde sei. Vc pode amarrar as coisas para que o hibernate o avise de alterações e processar. Mas seria melhor que vc mesmo ativasses os triggers via repositorio. Bom, pelo menos se vc gosta de codigo bem organizado e automáticamente testável.[/quote]

Aparentemente é magico sim =x … pelomenos quanto a isso…

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/event/package-summary.html

AutoFlushEventListener "Defines the contract for handling of session auto-flush events."" DeleteEventListener "Defines the contract for handling of deletion events generated from a session." DirtyCheckEventListener "Defines the contract for handling of session dirty-check events." EventSource EvictEventListener "Defines the contract for handling of evict events generated from a session." FlushEntityEventListener FlushEventListener "Defines the contract for handling of session flush events." Initializable "An event listener that requires access to mappings to initialize state at initialization time." InitializeCollectionEventListener "Defines the contract for handling of collection initialization events generated by a session." LoadEventListener "Defines the contract for handling of load events generated from a session." LockEventListener "Defines the contract for handling of lock events generated from a session." MergeEventListener "Defines the contract for handling of merge events generated from a session." PersistEventListener "Defines the contract for handling of create events generated from a session." PostDeleteEventListener "Called after deleting an item from the datastore" PostInsertEventListener "Called after insterting an item in the datastore" PostLoadEventListener "Occurs after an an entity instance is fully loaded." PostUpdateEventListener "Called after updating the datastore" PreDeleteEventListener "Called before deleting an item from the datastore" PreInsertEventListener "Called before inserting an item in the datastore" PreLoadEventListener "Called before injecting property values into a newly loaded entity instance." PreUpdateEventListener "Called before updating the datastore" RefreshEventListener "Defines the contract for handling of refresh events generated from a session." ReplicateEventListener "Defines the contract for handling of replicate events generated from a session." SaveOrUpdateEventListener "Defines the contract for handling of update events generated from a session"

la tem tudo que preciso… e tudo que uma Trigger faz… so preciso saber agora como injetar os Ouvintes ^^ … estou procurando na API o lugar certo [/quote]

Ele não é mágico não. Vc tem que ter atenção a quanto os eventos são enviados.
O Hibernate usa unidades de trabalho para determinar as alterações que serão feitas no banco. Entao é possivel que o seu repositorio receba uma ordem de save e que o hibernate não faça nenhuma alteração no banco por determinar que nada mudou. Contudo a ação de save , do ponto de vista do negocio deveria ser gerado um log de acessos ( acessos, não alterações). Se usar o listener do hibernate é possivel que o log não seja escrito. Se o listener é do repsoitorio ele sera sempre escrito.

[quote=sergiotaborda]Ele não é mágico não. Vc tem que ter atenção a quanto os eventos são enviados.
O Hibernate usa unidades de trabalho para determinar as alterações que serão feitas no banco. Entao é possivel que o seu repositorio receba uma ordem de save e que o hibernate não faça nenhuma alteração no banco por determinar que nada mudou. Contudo a ação de save , do ponto de vista do negocio deveria ser gerado um log de acessos ( acessos, não alterações). Se usar o listener do hibernate é possivel que o log não seja escrito. Se o listener é do repsoitorio ele sera sempre escrito.
[/quote]

depois de algumas pesquisas sergio, eu vi que dava pra fazer trigger de forma bem simples… com anotações, so adcionar a classe entidade as anotações

[code]@PrePersist //antes de inserir
@PostPersist //depois de inserir

@PreRemove //antes de deletar
@PostRemove //depois de deletar

@PreUpdate //antes de atualizar
@PostUpdate //depois de atualizar

@PostLoad //Depois de ler do banco de dados[/code]

com estas anotações em um método, o hibernate vai fazer chamada do método no momento exato, igual um trigger… por exemplo

[code]@Entity
public class ItemDaNotaFiscal {
@Id
@GeneratedValue
private id;
private NotaFiscal notaFiscal;
private Produto produto;
private int quantidade;
private double preco;
private Date dataDeRegistro;
private Date dataDeEmissaoDaNota;
@Transient
private precoTotal;

 //getters n setters...

 @PrePersist
 public void beforePersist() {
      calculaPrecoTotal();
      verificaEstoque();
      atualizaDataDeRegistro();
 }
 
 @PostPersist
 public void afterPersist() {
      atualizaEstoque();
 }
 
 @PostLoad
 public void afterLoad() {
      calculaPrecoTotal();
 }

 @Transient
 private void verificaEstoque() {
     if (getProduto().getEstoque() < getQuantidade())
           throw new EstoqueException("Estoque Insuficiente");
 }
 
 @Transient
 private void atualizaEstoque() {
     getProduto().setEstoque(getProduto().getEstoque() - quantidade);
     Repositories.marge(getProduto());
 }

 @Transient
 private void atualizaDataDeRegistro() {
     setDataDeRegistro(new Date());
 }

 @Transient
 public void calculaPrecoTotal() {
     setPrecoTotal(getQuantidade() * getPreco());
 }

}[/code]

Se vc não quiser fazer dentro da classe entidade, pode fazer a chamada através de uma classe que audita esta entidade, para tal, basta adcionar a anotação @EntityListener a classe, por exemplo

[code]@Entity
@EntityListener(class={ItemDaNotaFiscalTrigger.class})
public class ItemDaNotaFiscal {
@Id
@GeneratedValue
private id;
private NotaFiscal notaFiscal;
private Produto produto;
private int quantidade;
private double preco;
private Date dataDeRegistro;
private Date dataDeEmissaoDaNota;
@Transient
private precoTotal;

 //getters n setters...

}[/code]

ai na classe de escuta, vc deve fazer os métodos receberem o objeto a ser modificado

[code]

public class ItemDaNotaFiscalTrigger {
@PrePersist
public void beforePersist(ItemDaNotaFiscal itemDaNotaFiscal) {
itemDaNotaFiscal.setDataDeRegistro(new Date());
//… etc etc etc
}
}[/code]