Duvida transação EJB

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

[code]//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§;

Email email = new Email();
email.setPessoa§;[/code]
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.

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.

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.

ok…

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

//Usuario @Id @Basic(optional = false) @Column(name = "usu_id", nullable = false) private Long usuId; @Basic(optional = false) @Column(name = "usu_login", nullable = false, length = 2147483647) private String usuLogin; @Basic(optional = false) @Column(name = "usu_senha", nullable = false, length = 2147483647) private String usuSenha; @Basic(optional = false) @Column(name = "usu_dica_senha", nullable = false, length = 2147483647) 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 = 2147483647) private String pesCpf; @Basic(optional = false) @Column(name = "pes_nome", nullable = false, length = 2147483647) 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 = 2147483647) private String pesRg; @Column(name = "pes_data_expedicao") @Temporal(TemporalType.DATE) private Date pesDataExpedicao; @Column(name = "pes_orgao_expedidor", length = 2147483647) 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 = 2147483647) 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 = 2147483647) 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 = 2147483647) private String endLogradouro; @Column(name = "end_quadra", length = 2147483647) private String endQuadra; @Column(name = "end_lote", length = 2147483647) private String endLote; @Column(name = "end_num", length = 2147483647) private String endNum; @Column(name = "end_complemento", length = 2147483647) private String endComplemento; @Basic(optional = false) @Column(name = "end_bairro", nullable = false, length = 2147483647) private String endBairro; @Basic(optional = false) @Column(name = "end_cep", nullable = false, length = 2147483647) private String endCep; @Basic(optional = false) @Column(name = "end_cidade", nullable = false, length = 2147483647) 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 = 2147483647) 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 = 2147483647) private String farmoAnoFormatura; @Column(name = "farmo_instituicao_formatura", length = 2147483647) 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 = 2147483647) 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 = 2147483647) private String farmoNumeroFiliacao; @Basic(optional = false) @Column(name = "farmo_ctps", nullable = false, length = 2147483647) 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 = 2147483647) private String farmaCnpj; @Column(name = "farma_controle") private Integer farmaControle; @Column(name = "farma_recado", length = 2147483647) private String farmaRecado; @Basic(optional = false) @Column(name = "farma_nome_fantasia", nullable = false, length = 2147483647) private String farmaNomeFantasia; @Column(name = "farma_observacao", length = 2147483647) private String farmaObservacao; @Column(name = "farma_referencia", length = 2147483647) private String farmaReferencia; @Column(name = "farma_logomarca", length = 2147483647) private String farmaLogomarca; @Basic(optional = false) @Column(name = "farma_razao_social", nullable = false, length = 2147483647) 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 = 2147483647) private String farmaAlvaraCrf; @Basic(optional = false) @Column(name = "farma_alvara_anvisa_federal", nullable = false, length = 2147483647) private String farmaAlvaraAnvisaFederal; @Column(name = "farma_aut_esp_anvisa_federal", length = 2147483647) private String farmaAutEspAnvisaFederal; @Basic(optional = false) @Column(name = "farma_alvara_visa_municipal", nullable = false, length = 2147483647) private String farmaAlvaraVisaMunicipal; @Basic(optional = false) @Column(name = "farma_alvara_func_municipal", nullable = false, length = 2147483647) private String farmaAlvaraFuncMunicipal; @Basic(optional = false) @Column(name = "farma_alvara_visa_estadual", nullable = false, length = 2147483647) private String farmaAlvaraVisaEstadual; @Column(name = "farma_inscricao_simples", length = 2147483647) 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 = 2147483647) private String farmaRespLegal; @Basic(optional = false) @Column(name = "farma_inscricao_estadual", nullable = false, length = 2147483647) 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.

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);
  }
}

É 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?

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?

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
josimarsis@gmail.com
josimarsis@hotmail.com