Erro ao fazer insercao em cascata

19 respostas
K
Possuo um relacionamento OneToMany entre Cliente e EmailCliente Classe Cliente
@Entity
@Table(name="Cliente", schema="Tecnicos")
public class Cliente implements Serializable {

    @Id
    @SequenceGenerator(name="SEQ_CLI", sequenceName="SEQ_CLIENTE", allocationSize=1, initialValue=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_CLI")
    @Column(name="cli_id", nullable=false)
    @Resolvable(colName="ID")
    private Integer id;

    @Column(name="cli_codext")
    @Resolvable(colName="CÓDIGO")
    private Integer codigoExterno;

    @Column(name="cli_fili")
    @Resolvable(colName="FILIAL")
    private Integer filial;

    @Column(name="cli_razaosocial", length=80)
    @Resolvable(colName="RAZÃO SOCIAL")
    private String razaoSocial;

    @Column(name="cli_nomefantasia", length=80)
    @Resolvable(colName="NOME FANTASIA")
    private String nomeFantasia;

    @Column(name="cli_cnpj", length=20)
    private String cnpj;

    @Column(name="cli_inscest", length=30)
    private String InscEst;

    @Column(name="cli_endereco", length=200)
    private String endereco;

    @Column(name="cli_bairro", length=45)
    private String bairro;

    @Column(name="cli_cidade", length=50)
    private String cidade;

    @Column(name="cli_estado", length=2)
    private String estado;

    @Column(name="cli_cep", length=20)
    private String cep;

    @Column(name="cli_telefone", length=20)
    @Resolvable(colName="TELEFONE")
    private String telefone;

    @Column(name="cli_situreg", length=20)
    private String situ_reg;
    
    @Column(name="cli_emailPrincipal", length=150)
    @Resolvable(colName="EMAIL")
    private String emailPrincipal;

    @OneToMany(mappedBy="cliente", fetch=FetchType.LAZY)
    @Cascade(CascadeType.ALL)
    private Collection<EmailCliente> email;

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name="tecnico_cliente", schema="Tecnicos",
            joinColumns=@JoinColumn(name="teccli_cli_id"),
            inverseJoinColumns=@JoinColumn(name="teccli_tec_id"))
    private Collection<Tecnicos> tecnicos;

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name="questionario_cliente", schema="Tecnicos",
            joinColumns=@JoinColumn(name="cli_id"),
            inverseJoinColumns=@JoinColumn(name="ques_id"))
    private Collection<Questionario> questionarios;
Classe EmailCliente
@Entity
@Table(name="cli_email", schema="Tecnicos")
public class EmailCliente implements Serializable {

    @Id
    @SequenceGenerator(name="SEQ_CLIEMA", sequenceName="SEQ_CLIENTEEMAIL", allocationSize=1, initialValue=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_CLIEMA")
    @Column(name="cli_email_id", nullable=false)
    @Resolvable(colName="ID")
    private Integer id;

    @Column(name="cli_email_email", nullable=false)
    @Resolvable(colName="EMAIL")
    private String email;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="cliema_cli_id", insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.SAVE_UPDATE)
    @Resolvable(colName="CLIENTE")
    private Cliente cliente;
e estou fazendo o seguinte teste
public class teste {
    public static void main(String[] args) {
           Session session = HibernateUtil.getSessionFactory().openSession();
            GenericDAO<Cliente> dao = new GenericDAO<Cliente>(Cliente.class, session);
                try{
                    Cliente cli = new Cliente();                    
                    cli.setId(1);
                    cli.setNomeFantasia("teste");
                    cli.setBairro("dasdas");
                    cli.setEndereco("endereco");
                    
                    EmailCliente email1 = new EmailCliente();
                    email1.setEmail("email1saddasdasdada");
                    email1.setId(3);
                    email1.setCliente(cli);

                    EmailCliente email2 = new EmailCliente();
                    email2.setEmail("Email2dasdasdasdasdasda");
                    email2.setId(4);
                    email2.setCliente(cli);
                    
                    cli.setEmail(new HashSet<EmailCliente>());
                    cli.getEmail().add(email1);
                    cli.getEmail().add(email2);

                    dao.saveOrUpdate(cli);

                }catch(Exception ex){
                    JOptionPane.showMessageDialog(null, ex);
                    ex.printStackTrace();
        }
    }}

mais ele insere ou atualiza o cliente na tabela cliente mais nao insere nem atualiza os emails do cliente

19 Respostas

R

Ja viu o SQl que tá sendo gerado?

K

Hibernate: update Tecnicos.Cliente set cli_inscest=?, cli_bairro=?, cli_cep=?, cli_cidade=?, cli_cnpj=?, cli_codext=?, cli_emailPrincipal=?, cli_endereco=?, cli_estado=?, cli_fili=?, cli_nomefantasia=?, cli_razaosocial=?, cli_situreg=?, cli_telefone=? where cli_id=? Hibernate: update Tecnicos.cli_email set cli_email_cli_id=?, cli_email_email=? where cli_email_id=? Hibernate: update Tecnicos.cli_email set cli_email_cli_id=?, cli_email_email=? where cli_email_id=? Hibernate: delete from Tecnicos.questionario_cliente where cli_id=? Hibernate: delete from Tecnicos.tecnico_cliente where teccli_cli_id=?

K

@SequenceGenerator(name="SEQ_CLI", sequenceName="SEQ_CLIENTE", allocationSize=1, initialValue=1) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_CLI")

se eu tirar o mapeamento das sequencias usadas funcionaria normal?

R

ksio_thadeu:
@SequenceGenerator(name="SEQ_CLI", sequenceName="SEQ_CLIENTE", allocationSize=1, initialValue=1) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_CLI")

se eu tirar o mapeamento das sequencias usadas funcionaria normal?


Provavelmente não.

Qual o objetivo dessa anotação @Resolvable(colName=“ID”) ?

K

A anotacao @Resolvable é porque eu estou utilizando um model pra minha tabela
desenvolvido pelo Marky ObjectTableModel e ele utiliza annotations

L

use:

@OneToMany(cascade = CascadeType.ALL)
	@JoinColumn(name = "cli_email_id")
K

Mesmo fazendo a substituicao nao da certo
eu fiz para o id das classes Cliente e EmailCliente seja gerado por uma sequencia

se eu setar o id do cliente ou de algum emailCliente da erro na insercao ou alteracao;

K

Alguém???

K

Quando eu defino que o id do meu objeto será gerado através de uma sequencia do banco de dados, eu não posso setar o id com um número para fazer a inserção???

Paulo_Silveira

Afinal, voce esta ou nao esta invocando o setId? se é uma insercao, nao deveria, ja que quer que seja usada a sequence.

remova o setId, e cole a sql pra gente dos inserts. tambem poste o codigo do seu generic dao, e se voce esta ou nao usando cascade no relacionamento.

K
public class GenericDAO<T> implements DAO<T>{
 
    private Session session;
    private Transaction tx;
    private Class<T> classe;

    public GenericDAO(Class<T> classe, Session session){
        this.classe = classe;
        this.session = session;
    }
  
    @Override
    public void insert(T classe) {
        try{
            tx = session.beginTransaction();

            session.save(classe);
            tx.commit();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    @Override
    public void update(T classe) {
        try{
            tx = session.beginTransaction();
            session.update(classe);
            tx.commit();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    @Override
    public void delete(T classe) {
        try{
            tx = session.beginTransaction();
            session.update(classe);
            tx.commit();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    @Override
    public List<T> findAll() {
        try{
            Criteria c = session.createCriteria(this.classe);
            return c.list();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;            
        }
    }

    public List<T> findByName(Object coluna ,Object d) {
        try{
            Criteria c = session.createCriteria(this.classe);
            c.add(Restrictions.ilike(coluna.toString(), "%"+d.toString()+"%"));
            c.addOrder(Order.asc(coluna.toString()));
            return c.list();
        }
        catch(HibernateException ex){
            throw ex;
        }
    }

    public T findByID(Integer id) throws HibernateException {
         try{
            return (T) session.get(this.classe, id);
        }
        catch(HibernateException ex){
            throw ex;
        }
    }

    public void saveOrUpdate(T clazz) throws HibernateException {
        try{
            tx = session.beginTransaction();
            session.saveOrUpdate(clazz);
            tx.commit();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    public List<T> findByBetweenDate(Object coluna, Date inicio, Date fim) {
        try{
            tx = session.beginTransaction();
            Criteria c = session.createCriteria(this.classe);
            c.add(Restrictions.between(coluna.toString(), inicio, fim));
            
            return c.list();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    public List<T> findByAttributteEquals(String atributo, Object valor) {
        try{
            tx = session.beginTransaction();
            Criteria c = session.createCriteria(this.classe);
            c.add(Restrictions.eq(atributo, valor));
            return c.list();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

    public List<T> listByQuery(String query) {
        try{
            tx = session.beginTransaction();
            return session.createQuery(query).list();
        }
        catch(HibernateException ex){
            tx.rollback();
            throw ex;
        }
    }

eu precisava se fosse possivel, outra maneira de gerar o id no banco de dados

Paulo_Silveira

o problema esta no mappedBy. como a lista de EmailCliente esta em Cliente mapeado com mappedBy, ele vai ignorar qualquer mudanca na colecao desse lado do relacionamento.

Voce precisa fazer o contrario, criar EmailClientes e fazer setClient(cliente) em vez de fazer setEmailCliente(new ArrayList…)

K

mais mesmo fazendo setCliente e setId em email cliente ele tenta fazer um update.
teria como fazer tipo, seo o email nao existir com aquele id ele insere e se existir ele atualiza
eu ja criei um metodo saveOrUpdate mais sempre ele tenta atualizar

Olha o exemplo que eu fiz
public class teste {
    public static void main(String[] args) {
           Session session = HibernateUtil.getSessionFactory().openSession();
            GenericDAO<EmailCliente> dao = new GenericDAO<EmailCliente>(EmailCliente.class, session);
            GenericDAO<Cliente> dao2 = new GenericDAO<Cliente>(Cliente.class, session);
                try{
                    Cliente cli = dao2.findByID(1);
                    
                    cli.setNomeFantasia("teste3");
                    cli.setBairro("dasdas3");
                    cli.setEndereco("endereco3");
                    
                    EmailCliente email1 = new EmailCliente();
                    email1.setEmail("emaildasdasd1");
                    email1.setId(8);
                    email1.setCliente(cli);

                    EmailCliente email2 = new EmailCliente();
                    email2.setEmail("Emaildasdasdasdasdasdas");
                    email2.setId(3);
                    email2.setCliente(cli);

                    EmailCliente email3 = new EmailCliente();
                    email3.setEmail("email3");
                    email3.setCliente(cli);
                    email3.setId(9);

                    
                   

                    dao.saveOrUpdate(email2);
                    dao.saveOrUpdate(email3);
                    dao.saveOrUpdate(email1);
                    //dao.insert(email1);
                    //dao.insert(email2);
                    //dao.insert(email3);

                }catch(Exception ex){
                    JOptionPane.showMessageDialog(null, ex);
                    ex.printStackTrace();
                }

    }
}
Paulo_Silveira

remova todos os email.setId()

K

sim, retirei todos os setId(), eu precisava fazer tipo, cliente 1 com emails 1,2,3,4 - cliente 2 emails 1,2
para cada cliente iniciaria uma nova sequencia

Paulo_Silveira

poste o codigo que voce esta usando sem os setIds, lembrando de fazer email.setCliente em vez de cliente.setEmails(list) e ponha entao a saida SQL. Isso ja deveria ser o suficiente.

K
funcionou com o teste
Cliente cli = dao2.findByID(1);
                    
                    cli.setNomeFantasia("teste3");
                    cli.setBairro("dasdas3");
                    cli.setEndereco("endereco3");
                    
                    EmailCliente email1 = new EmailCliente();
                    email1.setEmail("emaildasdasd1");
                 
                    email1.setCliente(cli);

                    EmailCliente email2 = new EmailCliente();
                    email2.setEmail("Emaildasdasdasdasdasdas");
                 
                    email2.setCliente(cli);

                    EmailCliente email3 = new EmailCliente();
                    email3.setEmail("email3");
                    email3.setCliente(cli);
                 

                   
                    dao.insert(email1);
                    dao.insert(email2);
                    dao.insert(email3);

mais tem como para cada cliente fosse inciado uma nova sequencia, pensei em criar uma trigger no banco de dados para essa funcao mais nao sei se funciona, também vi um um post falando trigger no hibernate so que nao sei se é possível

Paulo_Silveira

nao entendi o que voce quer agora. pode exemplificar melhor?

K

Eu tenho a classe cliente e a emailClientee no banco de dados respectivamente
a minha tabela cli_email no banco possui os campos (id_email, email, id_cliente)
o que eu queria é que quando for inserir um email para um cliente ele recuperace o ultimo valor do id_email e adicionace 1
e para cada cliente iniciaria uma nova sequencia de id_email, ex cliente1 emails, 1,2,3, cliente 2 emails, 1,2,3,4
se eu adicionar um email para o cliente1 o proximo id_email seria o 4 e se fosse para o cliente 2 seria o 5

tentei criar a seguinte trigger no banco para essa funcao

create or replace trigger tg_email_cliente
  before insert on CLI_EMAIL
  for each row
begin

  begin
    select nvl(max(cli_email_id),0)+1
      into :new.cli_email_id
      from CLI_EMAIL
     where cli_email_cli_id = :new.cli_email_cli_id;
  exception
    when no_data_found then
      :new.cli_email_id := 1;
  end;

end tg_email_cliente;
Criado 18 de fevereiro de 2011
Ultima resposta 21 de fev. de 2011
Respostas 19
Participantes 4