user3576248
user3576248

Reputation: 45

JPA/hibernate error violation of foreign key constraint

I'm new to hibernat and i have two class and I'm trying to save the data in a Derby embedded database , however when I save the class 'produto ' with foreign key from the sale appears the following error: Error:

Caused by: ERROR 23503: INSERT on table 'PRODUTOS' caused a violation of foreign key constraint 'FKIOY8UEWC87473SNMMUOPJKUVB' for key (236).  The statement has been rolled back.
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.impl.sql.execute.ForeignKeyRIChecker.doCheck(Unknown Source)
    at org.apache.derby.impl.sql.execute.RISetChecker.doFKCheck(Unknown Source)
    at org.apache.derby.impl.sql.execute.InsertResultSet.normalInsertCore(Unknown Source)
    at org.apache.derby.impl.sql.execute.InsertResultSet.open(Unknown Source)
    at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(Unknown Source)
    at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source)
    ... 82 more

class Venda:

@Entity
@Table(name = "Venda")
@Access(value = AccessType.PROPERTY)
public class Venda {

    @Id
    @GeneratedValue
    @Column(name = "venda_id")
    public Long getId() {
        return id;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "produtos_id")
    public List<Produtos> getProdutos() {
        return produtos;
    }

    public void setProdutos(List<Produtos> produtos) {
        this.produtos = produtos;
    }

    [...]
}

class Produtos:

@Entity
@Table(name = "Produtos")
@Access(value = AccessType.PROPERTY)
public class Produtos {       

    @Id
    @GeneratedValue
    @Column(name = "produtos_id")
    public Long getId() {
        return id;
    }


    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "venda_id", nullable = false)
    public Venda getVenda() {
        return venda;
    }

    [...]
}

Saving:

EntityManagerFactory factory =   Persistence.createEntityManagerFactory("cliente");
EntityManager manager = factory.createEntityManager();
manager.getTransaction().begin();
manager.persist(venda);
for (Produtos produto : produtos) {
    produto.setVenda(venda);
}
for (Produtos produto : produtos) {

    manager.persist(produto);
}

manager.getTransaction().commit();
manager.close();
factory.close();

Upvotes: 2

Views: 7689

Answers (3)

Ben
Ben

Reputation: 3518

Beside the other answers:

...violation of foreign key constraint 'FKIOY8UEWC87473SNMMUOPJKUVB'...

  1. Without knowing what FKIOY8UEWC87473SNMMUOPJKUVB exactly means, it's not easy to identify the real problem (only by reading your code).
    It may be possible, that there exists an constraint in the database, which was removed (later) in code.
    You should check first, how the constraint named FKIOY8UEWC87473SNMMUOPJKUVB is defined.
  2. You can define your own FK-Names in the Hibernate mapping file hbm.xml:

    <many-to-one class="sample.SampleEntity" fetch="select" foreign-key="FK_sampleNameForFK" name="sample">
        <column name="sample_id"/>
    </many-to-one>
    

Upvotes: 2

Ish
Ish

Reputation: 4154

@JoinColumn should only be specified on one side of the relationship. It is usually placed on the side of the owning entity. In the Many-To-One and One-To-Many bi-directional relationship, this is usually placed on the field mapped with @ManyToOne.

So, I suggest to remove the @JoinColumn mapping on your getProdutos() method. Just leave one @JoinColumn on the many side.

Also, since this is a bi-directional relationship, you should specify a mappedBy attribute on the @OneToMany annotation to indicate that this is the inverse side of the relationship.

Here's a sample resulting code, after applying my suggestions:

@Entity
public class Venda {
...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="venda")    
    public List<Produtos> getProdutos() {
        return produtos;
    }
...
}

@Entity
public class Produtos {       
...
    @ManyToOne
    @JoinColumn(name = "venda_id", nullable = false)
    public Venda getVenda() {
        return venda;
    }
...
}

Upvotes: 1

mvb13
mvb13

Reputation: 1584

You've put cascade = CascadeType.ALL in Venda entity class. This means that Produto list is saved on Venda setting. As a result the second time you try to save Produto gives you constraint violation exception cause it has been already saved.

Upvotes: -1

Related Questions