Saving ID from a table with two Primary Keys with Hibernate

Asked

Viewed 1,439 times

1

Hello, I am having a problem while saving data in one last table. Well, this table has two Foreign Keys and the same are Primary Keys:

inserir a descrição da imagem aqui

When going to Controller, save the table, I use the following codes:

 itv.setId();
    itv.setIngresso(ing);
    itv.setVenda(ven);
    itv.setItvqtde(Integer.valueOf(request.getParameter("txtqtde")));

    itvDao.salvarItemVenda(itv);
    response.sendRedirect("my-tickents-buy.jsp");

Here is my Itemvendadao:

 public void salvarItemVenda(ItemVenda itv){


    try {

    s = new ConnectionFactory().getSessionFactory();
    tx = s.beginTransaction();
    s.save(itv);
    tx.commit();
    s.close();

    JOptionPane.showMessageDialog(null, "Item venda salva com sucesso");


    } catch (Exception e) {

        tx.rollback();

      JOptionPane.showMessageDialog(null, "Erro ao salvar item venda" +e.getMessage());
      s.close();


    }


}

What do I need to put in itv.setId()? When mapped it creates this method to save the sale item ID, the sale item ID is two: the ticket object and the sale object, both are already being saved above with the code:

 itv.setIngresso(ing);
    itv.setVenda(ven);

Again, what we need to put on itv.setId.()?

Here is Itemvenda.java (mapped automatically by Hibernate)

public class ItemVenda  implements java.io.Serializable {


 private ItemVendaId id;
 private Ingresso ingresso;
 private Venda venda;
 private int itvqtde;

public ItemVenda() {
}

public ItemVenda(ItemVendaId id, Ingresso ingresso, Venda venda, int itvqtde) {
   this.id = id;
   this.ingresso = ingresso;
   this.venda = venda;
   this.itvqtde = itvqtde;
}

public ItemVendaId getId() {
    return this.id;
}

public void setId(ItemVendaId id) {
    this.id = id;
}
public Ingresso getIngresso() {
    return this.ingresso;
}

public void setIngresso(Ingresso ingresso) {
    this.ingresso = ingresso;
}
public Venda getVenda() {
    return this.venda;
}

public void setVenda(Venda venda) {
    this.venda = venda;
}
public int getItvqtde() {
    return this.itvqtde;
}

public void setItvqtde(int itvqtde) {
    this.itvqtde = itvqtde;
}

And Itemvendaid.java is as follows:

public class ItemVendaId  implements java.io.Serializable {


 private int itvvencodigo;
 private int itvingressocodigo;

public ItemVendaId() {
}

public ItemVendaId(int itvvencodigo, int itvingressocodigo) {
   this.itvvencodigo = itvvencodigo;
   this.itvingressocodigo = itvingressocodigo;
}

public int getItvvencodigo() {
    return this.itvvencodigo;
}

public void setItvvencodigo(int itvvencodigo) {
    this.itvvencodigo = itvvencodigo;
}
public int getItvingressocodigo() {
    return this.itvingressocodigo;
}

public void setItvingressocodigo(int itvingressocodigo) {
    this.itvingressocodigo = itvingressocodigo;
}

3 answers

1

If the set of two or more columns that combined will never repeat, you do not need (and should not) create an extra column only to serve as a primary key (as @Shura16 suggested). You will only be creating a totally unnecessary column aimed only at its ease in development and running away from the performance and good data integrity in the database.

In your case, you need to create a composite key. Simple as that. At JPA there are two ways to do this. One is through Idclass and the other, which I recommend, is through Embeddedid and Embeddable.

Let’s say you have a Class A, a Class B, and a third Class C where your primary key is composed of the Class A and B union.

Would look like this:

Class A:

@Entity
@Table(name = "CLASSE_A")
public class ClasseA {

    @Id
    @Column(name = "CLASSE_A_ID")
    private Long id;

}

Class B:

@Entity
@Table(name = "CLASSE_B")
public class ClasseB {

    @Id
    @Column(name = "CLASSE_B_ID")
    private String id;

}

Before creating class C, you must create a class that will incorporate Class A and Class B. This class will represent your composite key.

Class C PK:

@Embeddable
public class ClasseCPK {

    @Column(name = "CLASSE_A_ID", nullable = false)
    private Long classeAId;

    @Column(name = "CLASSE_B_ID", nullable = false)
    private String classeBId;

}

Note the @Embeddable annotation in Classecpk. This serves to inform JPA that this class will serve as a composite key. Note also that its attributes are only a reference to the type of attributes of Class A and B. That is, Long and String.

Finally our Class C will look like this:

Class C:

@Entity
@Table(name = "CLASSE_C")
public class ClasseC {

    @EmbeddedId
    private ClasseCPK pk = new ClasseCPK();

    @ManyToOne
    @JoinColumn(name = "CLASSE_A_ID", referencedColumnName = "CLASSE_A_ID", nullable = false, updatable = false, insertable = false)
    private ClasseA classeA;

    @ManyToOne
    @JoinColumn(name = "CLASSE_B_ID", referencedColumnName = "CLASSE_B_ID", nullable = false, updatable = false, insertable = false)
    private ClasseB classeB;

}

And this ends the mapping.

One more detail. Just have Hibernate create the tables/columns for you if your project is small/amateur. If it is a large and important project, as for a financial institution and the like, never let Hibernate interfere with the structure of the database, because this same database can (and most likely will) be used in other systems and different languages.

Bonus: If an entity refers to another entity that has a composite key, you must use the @Joincolumns annotation.

1


Initially, I will recommend you to have a primary key for each table. this primary key would be an ID field.

If you need your foreign keys to be unique in the table use the UNIQUE attribute.

I will recommend you to use JPA annotations in your tables to help Hibernate (if you are already using xml recommend switching to Annotations):

@Entity
public class ItemVenda  implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "ingresso_id")
    private Ingresso ingresso;

    @ManyToOne
    @JoinColumn(name = "venda_id")
    private Venda venda;

    private int qtde;

    //getters e setters omitidos
}

You would also have the Sale and Ticket classes with their respective fields. And it would have only these three tables. The Itemvenda table would have the fields: id, ticket, sales_id, Qtde

Always letting Hibernate take care of it for you.

In this case your setId() method of the class Itemvenda would only be used in cases of update.

  • 1

    So would you recommend me to create an ID in the sales item table? It would look like this: create table itemvenda( itvcodigo integer not null auto_increment Primary key, );

  • Exactly and that would be the code for manual creation. Still, I recommend that you configure Hibernate to automatically create/update tables for you (considering that it is still in the development phase and there is no important data in the database).

0

Hello,

Directly answering your question "..what needs to be put on itv.setId()?"

As your code this ID is formed by an object ItemVendaId, then just instantiate it at the time of recording that everything should work.

Since you didn’t show the code for the Ticket and Sale classes, I’m guessing the names of their Ids. Follow example:

itv.setId(new ItemVendaId(ven.getitvvencodigo(), ing.getitvingressocodigo()));
itv.setIngresso(ing);
itv.setVenda(ven);
itv.setItvqtde(Integer.valueOf(request.getParameter("txtqtde")));
itvDao.salvarItemVenda(itv);
response.sendRedirect("my-tickents-buy.jsp");

In any case, as well as the other colleagues who responded earlier, I do not recommend this type of mapping.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.