Duvida transação EJB

8 respostas
josimarsis

Olá é possivel em algum momento trazer o controle de transação do EJB para mim? Ex:

//Situação
//Desta forma com o EJB controlando a transação se desse um erro ao salvar o email a pessoa ja estaria no banco
//de dados pois ele ja teria dado um comit.
Pessoa p = new Pessoa();
p = em.merge(p);

Email email = new Email();
email.setPessoa(p);
Seria possível de alguma forma eu dar um comit somente no final deste codigo? Eu até consegui salvar estes dados em cascata mais a relação de onde eu tirei este exemplo tem 6 tabelas que estão entre si relacionadas e não consegui fazer o cascade de todas por não entender direito como funciona ainda. Se eu conseguisse dar um comit somente no final da transação eu conseguiria garantir a integridade dos meus dados e por hora resolveria meu problema.

8 Respostas

A

josimarsis, sua duvida nao ficou clara.

Respondendo sua pergunta: Se o seu projeto EJB foi configurado para que a transacao seja controlado pelo container (CMT / JTA), entao a resposta eh nao, lembrando que voce pode trabalhar com EJB sem que tenha a transacao controlada pelo mesmo (BMT). Mas ate ai, voce deixaria de usar um recurso poderoso da especificacao.

Discordo com o que voce sitou neste comentario. Alias, eh justamente o inverso. Caso ocorra algum erro de RuntimeException (que acredito que seja o caso), se voce estiver tentando realizar esses inserts tudo na mesma transacao, o container automaticamente ira realizar um rollback de tudo o que fez pra voce.

Eu aconselharia voce a resolver a questao do mapeamento pois acredito que o erro esteja ai.

Posta os codigos das entidades para ver aonde esta o erro.

josimarsis

Alexamdo, realmente acho que minha pergunta não ficou boa, todo o meu problema esta acontecendo
devido eu não conseguir entender direito como funciona o cascade no JPA, tenho uma pagina jsf que
alimenta 8 tabelas no banco de dados que estão entre si relacionadas. Na minha concepção eu deveria salvar
tudo em uma unica operação utilizando o cascade porem não consegui. Eu ja usei JPA com desenvolvimento desktop
porem lá eu tinha total controle sobre o EntityManager agora com o EJB estou perdido. Realmente estou utilizando JTA
Segue o modelo do banco de dados.

A

ok…

O modelo de dados ficou claro. Necessito ver agora como voce realizou o mapeamento nas entidades. Seria possivel voce postar esses mapeamentos?

josimarsis

//Usuario @Id @Basic(optional = false) @Column(name = "usu_id", nullable = false) private Long usuId; @Basic(optional = false) @Column(name = "usu_login", nullable = false, length = [telefone removido]) private String usuLogin; @Basic(optional = false) @Column(name = "usu_senha", nullable = false, length = [telefone removido]) private String usuSenha; @Basic(optional = false) @Column(name = "usu_dica_senha", nullable = false, length = [telefone removido]) private String usuDicaSenha; @Column(name = "usu_tipo") private Short usuTipo; @JoinColumn(name = "pes_id", referencedColumnName = "pes_id") @OneToOne private Pessoa pesId;

//Pessoa @Id @Basic(optional = false) @Column(name = "pes_id", nullable = false) private Long pesId; @Basic(optional = false) @Column(name = "pes_cpf", nullable = false, length = [telefone removido]) private String pesCpf; @Basic(optional = false) @Column(name = "pes_nome", nullable = false, length = [telefone removido]) private String pesNome; @Basic(optional = false) @Column(name = "pes_sexo", nullable = false) private short pesSexo; @Basic(optional = false) @Column(name = "pes_data_nascimento", nullable = false) @Temporal(TemporalType.DATE) private Date pesDataNascimento; @Column(name = "pes_estado_civil") private Short pesEstadoCivil; @Column(name = "pes_rg", length = [telefone removido]) private String pesRg; @Column(name = "pes_data_expedicao") @Temporal(TemporalType.DATE) private Date pesDataExpedicao; @Column(name = "pes_orgao_expedidor", length = [telefone removido]) private String pesOrgaoExpedidor; @OneToOne(mappedBy = "pesId") private Usuario usuario; @OneToMany(cascade = CascadeType.MERGE, mappedBy = "pesId") private Set<Farmaceutico> farmaceuticoSet = new HashSet<Farmaceutico>(); @OneToMany(mappedBy = "pesId") private Set<Email> emailSet = new HashSet<Email>(); @OneToMany(cascade = CascadeType.MERGE, mappedBy = "pesId") private Set<Cliente> clienteSet = new HashSet<Cliente>(); @OneToMany(mappedBy = "pesId") private Set<Telefone> telefoneSet = new HashSet<Telefone>(); @OneToMany(mappedBy = "pesId") private Set<Endereco> enderecoSet = new HashSet<Endereco>();

//Email @Id @Basic(optional = false) @Column(name = "email_id", nullable = false) private Long emailId; @Basic(optional = false) @Column(name = "email_descricao", nullable = false, length = [telefone removido]) private String emailDescricao; @Basic(optional = false) @Column(name = "email_tipo", nullable = false) private short emailTipo; @JoinColumn(name = "farma_cnpj", referencedColumnName = "farma_cnpj") @ManyToOne private Farmacia farmaCnpj; @JoinColumn(name = "pes_id", referencedColumnName = "pes_id") @ManyToOne private Pessoa pesId;

//Telefone @Id @Basic(optional = false) @Column(name = "tel_id", nullable = false) private Long telId; @Basic(optional = false) @Column(name = "tel_fone", nullable = false, length = [telefone removido]) private String telFone; @Basic(optional = false) @Column(name = "tel_tipo", nullable = false) private short telTipo; @JoinColumn(name = "farma_cnpj", referencedColumnName = "farma_cnpj") @ManyToOne private Farmacia farmaCnpj; @JoinColumn(name = "pes_id", referencedColumnName = "pes_id") @ManyToOne private Pessoa pesId;

//Endereco @Id @Basic(optional = false) @Column(name = "end_id", nullable = false) private Long endId; @Basic(optional = false) @Column(name = "end_tipo_logradouro", nullable = false) private short endTipoLogradouro; @Basic(optional = false) @Column(name = "end_logradouro", nullable = false, length = [telefone removido]) private String endLogradouro; @Column(name = "end_quadra", length = [telefone removido]) private String endQuadra; @Column(name = "end_lote", length = [telefone removido]) private String endLote; @Column(name = "end_num", length = [telefone removido]) private String endNum; @Column(name = "end_complemento", length = [telefone removido]) private String endComplemento; @Basic(optional = false) @Column(name = "end_bairro", nullable = false, length = [telefone removido]) private String endBairro; @Basic(optional = false) @Column(name = "end_cep", nullable = false, length = [telefone removido]) private String endCep; @Basic(optional = false) @Column(name = "end_cidade", nullable = false, length = [telefone removido]) private String endCidade; @Basic(optional = false) @Column(name = "end_uf", nullable = false, length = 2) private String endUf; @JoinColumn(name = "farma_cnpj", referencedColumnName = "farma_cnpj") @ManyToOne private Farmacia farmaCnpj; @JoinColumn(name = "pes_id", referencedColumnName = "pes_id") @ManyToOne private Pessoa pesId;

//Farmaceutico @Id @Basic(optional = false) @Column(name = "farmo_id", nullable = false) private Long farmoId; @Basic(optional = false) @Column(name = "farmo_data_alt_cadastro", nullable = false) @Temporal(TemporalType.TIMESTAMP) private Date farmoDataAltCadastro; @Basic(optional = false) @Column(name = "farmo_data_alt_situacao", nullable = false) @Temporal(TemporalType.TIMESTAMP) private Date farmoDataAltSituacao; @Basic(optional = false) @Column(name = "farmo_data_cadastro", nullable = false) @Temporal(TemporalType.TIMESTAMP) private Date farmoDataCadastro; @Basic(optional = false) @Column(name = "farmo_situacao", nullable = false) private short farmoSituacao; @Basic(optional = false) @Column(name = "farmo_crf", nullable = false, length = [telefone removido]) private String farmoCrf; @Basic(optional = false) @Column(name = "farmo_uf_crf", nullable = false, length = 2) private String farmoUfCrf; @Basic(optional = false) @Column(name = "farmo_ano_formatura", nullable = false, length = [telefone removido]) private String farmoAnoFormatura; @Column(name = "farmo_instituicao_formatura", length = [telefone removido]) private String farmoInstituicaoFormatura; @Basic(optional = false) @Column(name = "farmo_qualificacao", nullable = false) private short farmoQualificacao; @Basic(optional = false) @Column(name = "farmo_titulo_qualificacao", nullable = false, length = [telefone removido]) private String farmoTituloQualificacao; @Basic(optional = false) @Column(name = "farmo_filiado", nullable = false) private boolean farmoFiliado; @Column(name = "farmo_entidade_filiado") private Integer farmoEntidadeFiliado; @Column(name = "farmo_numero_filiacao", length = [telefone removido]) private String farmoNumeroFiliacao; @Basic(optional = false) @Column(name = "farmo_ctps", nullable = false, length = [telefone removido]) private String farmoCtps; @JoinColumn(name = "pes_id", referencedColumnName = "pes_id", nullable = false) @ManyToOne(optional = false) private Pessoa pesId; @OneToMany(cascade = CascadeType.MERGE, mappedBy = "farmoId") private Set<FarmoFarma> farmoFarmaSet = new HashSet<FarmoFarma>();

//Farmacia @Id @Basic(optional = false) @Column(name = "farma_cnpj", nullable = false, length = [telefone removido]) private String farmaCnpj; @Column(name = "farma_controle") private Integer farmaControle; @Column(name = "farma_recado", length = [telefone removido]) private String farmaRecado; @Basic(optional = false) @Column(name = "farma_nome_fantasia", nullable = false, length = [telefone removido]) private String farmaNomeFantasia; @Column(name = "farma_observacao", length = [telefone removido]) private String farmaObservacao; @Column(name = "farma_referencia", length = [telefone removido]) private String farmaReferencia; @Column(name = "farma_logomarca", length = [telefone removido]) private String farmaLogomarca; @Basic(optional = false) @Column(name = "farma_razao_social", nullable = false, length = [telefone removido]) private String farmaRazaoSocial; @Basic(optional = false) @Column(name = "farma_acesso_internet", nullable = false) private short farmaAcessoInternet; @Basic(optional = false) @Column(name = "farma_alvara_crf", nullable = false, length = [telefone removido]) private String farmaAlvaraCrf; @Basic(optional = false) @Column(name = "farma_alvara_anvisa_federal", nullable = false, length = [telefone removido]) private String farmaAlvaraAnvisaFederal; @Column(name = "farma_aut_esp_anvisa_federal", length = [telefone removido]) private String farmaAutEspAnvisaFederal; @Basic(optional = false) @Column(name = "farma_alvara_visa_municipal", nullable = false, length = [telefone removido]) private String farmaAlvaraVisaMunicipal; @Basic(optional = false) @Column(name = "farma_alvara_func_municipal", nullable = false, length = [telefone removido]) private String farmaAlvaraFuncMunicipal; @Basic(optional = false) @Column(name = "farma_alvara_visa_estadual", nullable = false, length = [telefone removido]) private String farmaAlvaraVisaEstadual; @Column(name = "farma_inscricao_simples", length = [telefone removido]) private String farmaInscricaoSimples; @Basic(optional = false) @Column(name = "farma_tipo", nullable = false) private short farmaTipo; @Basic(optional = false) @Column(name = "farma_resp_legal", nullable = false, length = [telefone removido]) private String farmaRespLegal; @Basic(optional = false) @Column(name = "farma_inscricao_estadual", nullable = false, length = [telefone removido]) private String farmaInscricaoEstadual; @ManyToMany(mappedBy = "farmaciaSet") private Set<Cliente> clienteSet = new HashSet<Cliente>(); @OneToMany(cascade = CascadeType.MERGE, mappedBy = "farmaCnpj") private Set<FarmoFarma> farmoFarmaSet = new HashSet<FarmoFarma>(); @OneToMany(mappedBy = "farmaCnpj") private Set<Email> emailSet = new HashSet<Email>(); @OneToMany(mappedBy = "farmaCnpj") private Set<Telefone> telefoneSet = new HashSet<Telefone>(); @OneToMany(mappedBy = "farmaCnpj") private Set<Endereco> enderecoSet = new HashSet<Endereco>();

//FarmoFarma @Id @Basic(optional = false) @Column(name = "farmo_farma_id", nullable = false) private Long farmoFarmaId; @Basic(optional = false) @Column(name = "farmo_farma_situacao", nullable = false) private short farmoFarmaSituacao; @OneToMany(cascade = CascadeType.MERGE, mappedBy = "farmoFarmaId") private Set<Erro> erroSet = new HashSet<Erro>(); @JoinColumn(name = "farmo_id", referencedColumnName = "farmo_id", nullable = false) @ManyToOne(optional = false) private Farmaceutico farmoId; @JoinColumn(name = "farma_cnpj", referencedColumnName = "farma_cnpj", nullable = false) @ManyToOne(optional = false) private Farmacia farmaCnpj; @OneToMany(cascade = CascadeType.MERGE, mappedBy = "farmoFarmaId") private Set<Servico> servicoSet = new HashSet<Servico>();
Os relacionamentos foram gerados pelo netbeans eu so coloquei a estrategia de cascata e instanciei os Sets pra ficar mais facil de
se trabalhar! Eu estava usando List mais ele não aceita multiplos fetch e o Set aceita procurei na net o porque mais não encontrei.

A

Os cascades que vi, vc colocou somente para MERGE. Para efeito de testes, tenta colocar como ALL e verifica se o comportamento muda.

Em que momento esta falhando a persistencia em cascata? Para criar os filhos do relacionamento ou simplesmente para setar o pai (FK) nos relacionamento???

Como esta sendo persistido na sua base essas informacoes? Caso esteja sendo lancada alguma excecao, qual seria ela?

Nos agregados filhos que envolve lista, voce setou para os mesmos o pai?

Exemplo:
Na classe Farmacia:

public void adicionarTelefone(Telefone telefone) {
  if (telefone != null) {
    telefone.setFarmacia(this);
    this.listaTelefone.add(telefone);
  }
}
josimarsis

É porque eu estou utilizando o merge tanto pra persistência quanto pra alteração. O erro que mais acontece é
dizendo que o objeto é transient. Já procurei na net, li varios artigos mais ainda não consigo enteder direito como
fucniona o cascade. Eu estou certo em tentar persistir todos estas relações em uma unica operação?

A

Mas com o MERGE isso nunca vai rolar. No total, temos 5 tipos de configurar o cascade:

  • ALL (inclui as quatro funcionalidades abaixo numa soh declaracao)
  • MERGE
  • PERSIST
  • REFRESH
  • REMOVE

Se entendi bem, vc deveria no minimo estar usando o PERSIST, nao?

O MERGE eh utilizando quando queremos que um agregado seja atualizado na mesma cadeia de VOs que voce esta tentando persistir ou atualizar. Porem, ele nao inclui se o mesmo nao existir. Pra isso, teria que utilizar o PERSIST.

Faz o seguinte, primeiro: Quem eh a tabela pai do core do negocio? Farmacia? Qual o comportamento que voce esta tentando obter ao persistir a entidade Farmacia?
Que tabela voce ja possui carga e quais voce precisa inserir sob demanda?

josimarsis

Certo vou fazer os testes depois posto novamente, e obrigado pela ajuda! Na minha concepção se o objeto n possuísse
um Id o merge salvaria, caso contrário ele alteraria. Caso seja possível me add no msn ou gmail ai vai
[email removido]
[email removido]

Criado 2 de maio de 2010
Ultima resposta 2 de mai. de 2010
Respostas 8
Participantes 2