Sarthak
Sarthak

Reputation: 218

Issues with @ManyToMany hibernate mapping

I am new to web development. I have been trying to make an e commerce platform and using @ManyToMany mapping between product and wishlist using wishlist_product as the joining table.

Upon adding, I am not facing error, but the data is not been added in the join table. I have been trying to resolve this issue for 2 days now, but have been facing continuous failure. I have attached the code for both, wishlist and product below.

@Entity
@Table(name = "wishlist")
public class Wishlist {

    @Id
    @Column(name = "username")
    /*
     * @GeneratedValue(generator = "gen")
     * 
     * @GenericGenerator(name = "gen", strategy = "foreign", parameters
     * = @Parameter(name = "property", value = "login"))
     */
    private String username;

    @ManyToMany
    @JoinTable(name = "wishlist_product", 
                joinColumns = @JoinColumn(name = "username"),
                inverseJoinColumns = @JoinColumn(name = "product_id"))
    private List<Electronics> product;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "electronics")
@DiscriminatorColumn(name = "product_Type", discriminatorType = DiscriminatorType.STRING)
public class Electronics {

    @Id
    @GenericGenerator(name = "CamIdGenerator", strategy = "com.virtusa.neuralhack.vlx.IdGenerator.CameraIdGenerator")
    @GeneratedValue(generator = "CamIdGenerator")
    // @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "product_id")
    private String productId;

    private String askingPrice;

    @Column(name = "age")
    private String howOld;

    @Column(name = "model")
    private String model;

    @Column(name = "brand")
    private String brand;

    @Column(name = "description")
    private String description;

    transient private String email;

    @ManyToOne
    @JoinColumn(name = "username")
    private User_Login user;

    @ManyToMany
    @JoinTable(name = "wishlist_product", joinColumns = @JoinColumn(name = "product_id"), inverseJoinColumns = @JoinColumn(name = "username"))
    private List<Wishlist> wishlist;
public void addToWishlist(String email, String productId) {

    Session currentSession = manager.unwrap(Session.class);
    Wishlist wishlist = currentSession.get(Wishlist.class,email);
        
    //System.out.println(wishlist.getUser());
        
    Electronics product = currentSession.get(Electronics.class, productId);
    System.out.println(product);

    wishlist.addToWishlist(product);
        
    //product.addAWishlist(wishlist);
    //System.out.println(wishlist.getProduct().get(0));

    currentSession.saveOrUpdate(wishlist);
}

enter image description here

Upvotes: 1

Views: 249

Answers (2)

SternK
SternK

Reputation: 13111

You should do something like this:

@Entity
@Table(name = "wishlist")
public class Wishlist {

    @Id
    @Column(name = "username")
    private String username;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "wishlist_product", 
                joinColumns = @JoinColumn(name = "username"),
                inverseJoinColumns = @JoinColumn(name = "product_id"))
    private List<Electronics> products;
    
    public void addProduct(Electronics product) {
       products.add( product );
       product.getWishlists().add( this );
    }

    public void removeProduct(Electronics product) {
      products.remove( product );
      product.getWishlists().remove( this );
    }
}


@Entity
@Table(name = "electronics")
public class Electronics {

   @Id
   @Column(name = "product_id")
   private String productId;
   
   @ManyToMany(mappedBy = "products")
   private List<Wishlist> wishlists;
}
  1. Only an owning side of the bidirectional @ManyToMany should be mapped by the @JoinTable annotation. You should use the mappedBy on the other side.

  2. You should set cascade property on the owning side if you want to propagate persistent and other states.

  3. To preserve synchronicity between both sides, it’s good practice to provide helper methods for adding or removing child entities.

And your addToWishlist method will look like this:

public void addToWishlist(String email, String productId) {
   Session currentSession = manager.unwrap(Session.class);
   Wishlist wishlist = currentSession.get(Wishlist.class,email);
   Electronics product = currentSession.get(Electronics.class, productId);
   wishlist.addProduct(product);
   currentSession.saveOrUpdate(wishlist);
}

Upvotes: 1

Gordon from Blumberg
Gordon from Blumberg

Reputation: 199

Make sure you in the read-write transaction but not read-only.

And some advises:

  • do not use the cascade = CascadeType.ALL with the many-to-many association due to CascadeType.ALL includes CascadeType.REMOVE that in the case of many-to-many leads to too many entities are removed
  • use Set instead of List for to-many association when you don't need specific order.

Upvotes: 1

Related Questions