[Dúvida] [Dúvida] Erro "fk constraint fails" Hibernate após mapeamento de herança

9 respostas
rafaelob

Pessoa, recebo esse erro após mapear minha herança com “joined-subclass”

Primeiramente segue meu mapeamento:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 29/11/2010 17:43:35 by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
    <class catalog="locadora" name="Negocio.Beans.Usuario" table="usuario">
        <id name="idUsuario" type="java.lang.Integer">
            <column name="idUsuario"/>
            <generator class="native"/>
        </id>
        <many-to-one class="Negocio.Beans.Tipousuario" fetch="select" name="tipousuario">
            <column name="TipoUsuario_idTipoUsuario" not-null="true"/>
        </many-to-one>
        <property name="login" type="string">
            <column length="35" name="login" not-null="true" unique="true"/>
        </property>
        <property name="senha" type="string">
            <column length="45" name="senha" not-null="true"/>
        </property>
        <property name="nome" type="string">
            <column length="60" name="nome" not-null="true"/>
        </property>
        <joined-subclass catalog="locadora" name="Negocio.Beans.Cliente" table="cliente">
            <key column="Usuario_idUsuario"/>
            <property name="idCliente" type="java.lang.Integer">
                <column name="idCliente" unique = "true"/>
            </property>
            <property name="telefoneResidencial" type="string">
                <column length="20" name="telefoneResidencial" not-null="true"/>
            </property>
            <property name="telefoneCelular" type="string">
                <column length="20" name="telefoneCelular"/>
            </property>
            <property name="email" type="string">
                <column length="40" name="email"/>
            </property>
            <property name="dataNascimento" type="date">
                <column length="10" name="dataNascimento" not-null="true"/>
            </property>
            <property name="endereco" type="string">
                <column length="250" name="endereco" not-null="true"/>
            </property>
            <property name="rg" type="string">
                <column length="25" name="rg" not-null="true" unique="true"/>
            </property>
            <property name="cpf" type="string">
                <column length="25" name="cpf" not-null="true" unique="true"/>
            </property>
            <property name="sexo" type="char">
                <column length="1" name="sexo" not-null="true"/>
            </property>
            <property name="pendencia" type="boolean">
                <column name="pendencia" not-null="true"/>
            </property>
            <set inverse="true" name="reservas">
                <key>
                    <column name="Cliente_idCliente" not-null="true"/>
                </key>
                <one-to-many class="Negocio.Beans.Reserva"/>
            </set>
            <set inverse="true" name="dependentes">
                <key>
                    <column name="Cliente_idCliente" not-null="true"/>
                </key>
                <one-to-many class="Negocio.Beans.Dependente"/>
            </set>
        </joined-subclass>
        <joined-subclass catalog="locadora" name="Negocio.Beans.Administrador" table="administrador">
            <key column="Usuario_idUsuario"/>
            <property name="idAdministrador" type="java.lang.Integer">
                <column name="idAdministrador" unique = "true" />
            </property>
        </joined-subclass>
        <joined-subclass catalog="locadora" name="Negocio.Beans.Funcionario" table="funcionario">
            <key column="Usuario_idUsuario"/>
            <property name="idFuncionario" type="java.lang.Integer">
                <column name="idFuncionario" unique = "true" />
            </property>
            <property name="sexo" type="char">
                <column length="1" name="sexo" not-null="true"/>
            </property>
            <property name="telefone" type="string">
                <column length="20" name="telefone" not-null="true"/>
            </property>
            <property name="carteiraTrabalho" type="string">
                <column length="45" name="carteiraTrabalho" not-null="true" unique="true"/>
            </property>
            <set inverse="true" name="vendas">
                <key>
                    <column name="Funcionario_idFuncionario" not-null="true"/>
                </key>
                <one-to-many class="Negocio.Beans.Venda"/>
            </set>
            <joined-subclass catalog="locadora" name="Negocio.Beans.Gerente" table="gerente">
                <key column="Funcionario_idFuncionario"/>
                <property name="idGerente" type="java.lang.Integer">
                    <column name="idGerente" unique = "true" />
                </property>
            </joined-subclass>
        </joined-subclass>
    </class>
</hibernate-mapping>

Agora meus POJos

package Negocio.Beans;
// Generated 29/11/2010 21:10:28 by Hibernate Tools 3.2.1.GA



/**
 * Usuario generated by hbm2java
 */
public class Usuario implements java.io.Serializable {


    private Integer idUsuario;
    private Tipousuario tipousuario;
    private String login;
    private String senha;
    private String nome;

    public Usuario() {
    }

    public Usuario(Tipousuario tipousuario, String login, String senha, String nome) {
        this.tipousuario = tipousuario;
        this.login = login;
        this.senha = senha;
        this.nome = nome;
    }

    public Integer getIdUsuario() {
        return this.idUsuario;
    }

    public void setIdUsuario(Integer idUsuario) {
        this.idUsuario = idUsuario;
    }

    public Tipousuario getTipousuario() {
        return this.tipousuario;
    }

    public void setTipousuario(Tipousuario tipousuario) {
        this.tipousuario = tipousuario;
    }

    public String getLogin() {
        return this.login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getSenha() {
        return this.senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public String getNome() {
        return this.nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }
}

9 Respostas

rafaelob
package Negocio.Beans;
// Generated 29/11/2010 21:10:28 by Hibernate Tools 3.2.1.GA

import java.util.HashSet;
import java.util.Set;

/**
 * Funcionario generated by hbm2java
 */
public class Funcionario extends Usuario implements java.io.Serializable {

    private Integer idFuncionario;
    private char sexo;
    private String telefone;
    private String carteiraTrabalho;
    private Set vendas = new HashSet(0);

    public Funcionario() {
    }

    public Funcionario(char sexo, String telefone, String carteiraTrabalho, Tipousuario tipousuario, String login, String senha, String nome) {
        super(tipousuario, login, senha, nome);
        this.sexo = sexo;
        this.telefone = telefone;
        this.carteiraTrabalho = carteiraTrabalho;
    }

    public Funcionario(char sexo, String telefone, String carteiraTrabalho, Set vendas, Tipousuario tipousuario, String login, String senha, String nome) {
        super(tipousuario, login, senha, nome);
        this.sexo = sexo;
        this.telefone = telefone;
        this.carteiraTrabalho = carteiraTrabalho;
        this.vendas = vendas;
    }

    public Integer getIdFuncionario() {
        return this.idFuncionario;
    }

    public void setIdFuncionario(Integer idFuncionario) {
        this.idFuncionario = idFuncionario;
    }

    public char getSexo() {
        return this.sexo;
    }

    public void setSexo(char sexo) {
        this.sexo = sexo;
    }

    public String getTelefone() {
        return this.telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }

    public String getCarteiraTrabalho() {
        return this.carteiraTrabalho;
    }

    public void setCarteiraTrabalho(String carteiraTrabalho) {
        this.carteiraTrabalho = carteiraTrabalho;
    }

    public Set getVendas() {
        return this.vendas;
    }

    public void setVendas(Set vendas) {
        this.vendas = vendas;
    }
}


package Negocio.Beans;
// Generated 29/11/2010 21:10:28 by Hibernate Tools 3.2.1.GA

import java.util.Set;

/**
 * Gerente generated by hbm2java
 */
public class Gerente extends Funcionario implements java.io.Serializable {

    private Integer idGerente;

    public Gerente() {
    }

    public Gerente(char sexo, String telefone, String carteiraTrabalho, Tipousuario tipousuario, String login, String senha, String nome) {
        super(sexo, telefone, carteiraTrabalho, tipousuario, login, senha, nome);
    }

    public Gerente(char sexo, String telefone, String carteiraTrabalho, Set vendas, Tipousuario tipousuario, String login, String senha, String nome) {
        super(sexo, telefone, carteiraTrabalho, vendas, tipousuario, login, senha, nome);
    }

    public Integer getIdGerente() {
        return this.idGerente;
    }

    public void setIdGerente(Integer idGerente) {
        this.idGerente = idGerente;
    }
}

Ele gera isso: Hibernate: insert into locadora.tipousuario (textoTipo) values (?)
Hibernate: insert into locadora.tipousuario (textoTipo) values (?)
Hibernate: insert into locadora.usuario (TipoUsuario_idTipoUsuario, login, senha, nome) values (?, ?, ?, ?)
Hibernate: insert into locadora.administrador (idAdministrador, Usuario_idUsuario) values (?, ?)
Hibernate: insert into locadora.usuario (TipoUsuario_idTipoUsuario, login, senha, nome) values (?, ?, ?, ?)
Hibernate: insert into locadora.funcionario (idFuncionario, sexo, telefone, carteiraTrabalho, Usuario_idUsuario) values (?, ?, ?, ?, ?)
Hibernate: insert into locadora.gerente (idGerente, Funcionario_idFuncionario) values (?, ?)
30/11/2010 00:40:21 org.hibernate.util.JDBCExceptionReporter logExceptions
AVISO: SQL Error: 1452, SQLState: 23000
30/11/2010 00:40:21 org.hibernate.util.JDBCExceptionReporter logExceptions
GRAVE: Cannot add or update a child row: a foreign key constraint fails (locadora.gerente, CONSTRAINT fk_Gerente_Funcionario1 FOREIGN KEY (Funcionario_idFuncionario) REFERENCES funcionario (idFuncionario) ON DELETE NO ACTION ON UPDATE NO ACTION)

Eu fiz um teste, fui no banco de dados e mudei Funcionario_idFuncionario para não ser uma FK, e usando o hibernate consegui inserir no BD tranquilamente, inclusive com números IDs correspondentes…

Já pesquisei em tudo que é lugar, comecei a trabalhar hoje com o Hibernate, se alguém puder ajuda eu agradeço!

rafaelob
CREATE  TABLE IF NOT EXISTS `locadora`.`Funcionario` (
  `idFuncionario` INT NOT NULL AUTO_INCREMENT ,
  `sexo` CHAR NOT NULL ,
  `telefone` VARCHAR(20) NOT NULL ,
  `carteiraTrabalho` VARCHAR(45) NOT NULL ,
  `Usuario_idUsuario` INT NOT NULL ,
  PRIMARY KEY (`idFuncionario`) ,
  INDEX `fk_Funcionario_Usuario1` (`Usuario_idUsuario` ASC) ,
  UNIQUE INDEX `carteiraTrabalho_UNIQUE` (`carteiraTrabalho` ASC) ,
  CONSTRAINT `fk_Funcionario_Usuario1`
    FOREIGN KEY (`Usuario_idUsuario` )
    REFERENCES `locadora`.`Usuario` (`idUsuario` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `locadora`.`Gerente`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `locadora`.`Gerente` (
  `idGerente` INT NOT NULL AUTO_INCREMENT ,
  `Funcionario_idFuncionario` INT NOT NULL ,
  PRIMARY KEY (`idGerente`) ,
  INDEX `fk_Gerente_Funcionario1` (`Funcionario_idFuncionario` ASC) ,
  CONSTRAINT `fk_Gerente_Funcionario1`
    FOREIGN KEY (`Funcionario_idFuncionario` )
    REFERENCES `locadora`.`Funcionario` (`idFuncionario` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = big5
COLLATE = big5_bin;

Minhas duas tabelas

rafaelob

Coloquei o Log4J e olha isso:

Hibernate: 
    insert 
    into
        locadora.usuario
        (TipoUsuario_idTipoUsuario, login, senha, nome) 
    values
        (?, ?, ?, ?)
02:49:31,200 TRACE IntegerType:133 - binding '3' to parameter: 1
02:49:31,200 TRACE StringType:133 - binding 'lalala' to parameter: 2
02:49:31,200 TRACE StringType:133 - binding '2ea3' to parameter: 3
02:49:31,200 TRACE StringType:133 - binding 'joaoeae' to parameter: 4
Hibernate: 
    insert 
    into
        locadora.funcionario
        (idFuncionario, sexo, telefone, carteiraTrabalho, Usuario_idUsuario) 
    values
        (?, ?, ?, ?, ?)
02:49:31,216 TRACE IntegerType:126 - binding null to parameter: 1
02:49:31,216 TRACE CharacterType:133 - binding 'M' to parameter: 2
02:49:31,216 TRACE StringType:133 - binding '3323ae3' to parameter: 3
02:49:31,216 TRACE StringType:133 - binding '323ea24ae' to parameter: 4
02:49:31,216 TRACE IntegerType:133 - binding '18' to parameter: 5
Hibernate: 
    insert 
    into
        locadora.gerente
        (idGerente, Funcionario_idFuncionario) 
    values
        (?, ?)
02:49:31,216 TRACE IntegerType:126 - binding null to parameter: 1
02:49:31,216 TRACE IntegerType:133 - binding '18' to parameter: 2
02:49:31,262  WARN JDBCExceptionReporter:77 - SQL Error: 1452, SQLState: 23000
02:49:31,262 ERROR JDBCExceptionReporter:78 - Cannot add or update a child row: a foreign key constraint fails (`locadora`.`gerente`, CONSTRAINT `fk_Gerente_Funcionario1` FOREIGN KEY (`Funcionario_idFuncionario`) REFERENCES `funcionario` (`idFuncionario`) ON DELETE NO ACTION ON UPDATE NO ACTION)

Bem, ele tá passando como parâmetro de “id_Funcionario” o id_Usuario =( =( como eu resolvo isso??? é algo no meu mapeamento?

luxu

amigo seu eu fosse vc naum usaria Herança(extends) tente separar fazendo cada um com o seu…só para testar!

santanna106

Cara,

eu olhei rapidamente aqui, eu nunca implementei herança Joined utilizando os aquivos xml do hibernate só implementei utilizando JPA.

No JPA, se eu faço a classe Usuário herdar de Pessoa(Ex.), a chave primária da classe Usuário seria idPessoa(PK)(FK).

Ou seja não existiria Usuario_id(PK).

tente dá uma olhada nesta questão.

rafaelob

Olá, Santana

Bem, eu preciso que ele tenha a chave primária também. O intrigante é que todas relações de herança funcionam muito bem, só quando eu tenho uma hierarquia de 2º nível: Usuário->Funcionário->Gerente que isso acontece … Como pode perceber eu declarei um joined dentro do outro, para representar essa herança de 2º nível, eu já testei inserir funcionário, cliente e administrador(Que herdam em 1º grau de Usuário) e funciona corretamente .

O que está acontecendo, é que ao salvar Gerente, ele insere na tabela de Usuário, depois insere na tabela de Funcionário(Usando o id_Usuario gerado anteriormente), só que quando ele vai inserir em Gerente, ele deveria estar usando a o id_Funcionario que foi criado, mas ele usa o id_Usuario !!!

santanna106

rpz,

se vc está usando joined o que ocorre é o seguinte:

o idUsuario será a Pk de Funcionário e consequentemente será a de Gerente.

Eu não entendi a sua necessidade de criar uma chave artificial para Funcionário.

pq na prática todo Funcionário será um usuário e como Gerente herda de Funcionário, todo gerente tb será um usuário.

ou seja.

O idUsuário será a chave para as três tabelas.

rafaelob

Muito obrigado, você tem razão :wink:

santanna106

flw meu velho.

Bom Trabalho.

Criado 30 de novembro de 2010
Ultima resposta 30 de nov. de 2010
Respostas 9
Participantes 3