Issue
I have two entities, sale and sale_details. One sale will have many sale_details, but each sale_detail belongs to only one sale, my current code gives me a Repeated column in mapping for entity error.
Sale:
@Entity
@Table(name="Sales")
public class Sale implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sale_id", nullable = false)
private int sale_id;
@Column(name = "promotionid_fk")
private int promotionid_fk;
@Column(name = "grand_total", nullable = false)
private double grand_total;
@Column(name = "salespersonid_fk", nullable = false)
private int salespersonid_fk;
@Column(name = "customerid_fk", nullable = false)
private int customerid_fk;
@Column(name = "storeid_fk", nullable = false)
private int storeid_fk;
@Column(name = "expected_date", nullable = false)
private Date expected_date;
@Column(name = "pickup_date")
private Date pickup_date;
@Column(name = "initial_deposit_date", nullable = false)
private LocalDateTime initial_deposit_date;
@Column(name = "initial_deposit_type", nullable = false)
private String initial_deposit_type;
@Column(name = "initial_deposit_amount", nullable = false)
private double initial_deposit_amount;
@Column(name = "final_payment_date")
private LocalDateTime final_payment_date;
@Column(name = "final_payment_type")
private String final_payment_type;
@Column(name = "final_payment_amount")
private double final_payment_amount;
//maps one sale to many sale details relationship
@OneToMany(mappedBy = "sale", fetch = FetchType.LAZY)
private List<SaleDetails> sale_detail_list; //stores list of sale_detail entries where FK saleid_fk field is the ID of this sale
//default constructor, never used
public Sale() {
}
//creates new sale
public Sale(int promotionid_fk, double grand_total, int salespersonid_fk, int customerid_fk, int storeid_fk, Date expected_date, LocalDateTime initial_payment_date, String initial_payment_type, double initial_payment_amount) {
this.promotionid_fk = promotionid_fk;
this.grand_total = grand_total;
this.salespersonid_fk = salespersonid_fk;
this.customerid_fk = customerid_fk;
this.storeid_fk = storeid_fk;
this.expected_date = expected_date;
this.initial_deposit_date = initial_payment_date;
this.initial_deposit_type = initial_payment_type;
this.initial_deposit_amount = initial_payment_amount;
}
Sale_details:
@Entity
@Table(name = "sale_Details")
public class SaleDetails implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sale_detail_id")
private int saleDetailId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "saleid_fk")
private Sale sale;
@Column(name = "saleid_fk")
private int saleid_fk;
@Column(name = "productid_fk")
private int productid_fk;
@Column(name = "quantity_sold")
private int quantity_sold;
public SaleDetails(){
}
public SaleDetails(int saleid_fk, int productid_fk, int quantity_sold){
this.saleid_fk = saleid_fk;
this.productid_fk = productid_fk;
this.quantity_sold = quantity_sold;
}
Im trying to make the relationship bi-directional, what am I doing wrong here? From my understanding the owning side of the relationship is the many-to-one on the sale_details entity, and the mappedby in the sale entity is just referencing that there already is a mapping on the inverse side?
Full error stack trace:
Unable to build Hibernate SessionFactory
org.hibernate.MappingException: Repeated column in mapping for entity: com.owl.server.entities.Sale_Details column: saleid_fk (should be mapped with insert="false" update="false")
Solution
I would suggest you to follow java naming conventions. According to this roles:
Classes: Class names should be nouns, in mixed case with the first letter of each internal word capitalized.
Variables: Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters.
So, I would suggest you to correct your mapping in the following way:
@Entity
@Table(name="Sales")
public class Sale implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sale_id", nullable = false)
private int saleId;
@Column(name = "promotionid_fk")
private int promotionId;
// ...
//maps one sale to many sale details relationship
@OneToMany(mappedBy = "sale", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<SaleDetails> saleDetails;
// default constructor, should be present
// It is used by hibernate for entity instantiation
public Sale() {
saleDetails = new ArrayList<>();
}
// getters, setters
// The addSaleDetail() and removeSaleDetail() are utility methods that
// synchronize both ends whenever a child element is added or removed.
public void addSaleDetail(SaleDetails saleDetail)
{
saleDetails.add(saleDetail);
saleDetail.setSale(this);
}
public void removeSaleDetail(SaleDetails saleDetail)
{
saleDetails.remove(saleDetail);
saleDetail.setSale(null);
}
}
@Entity
@Table(name = "Sale_Details")
public class SaleDetails implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sale_detail_id")
private int saleDetailId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "saleid_fk")
private Sale sale;
// This should be removed
// @Column(name = "saleid_fk")
// private int saleid_fk;
@Column(name = "productid_fk")
private int productId;
// ...
public SaleDetails(){
}
// getters, setters
}
The value in the
mappedBy
referred to the field name of another side of the association.You can omit to use the
referencedColumnName
if the foreign key referred to the primary key field of target entity.
And an example of creation and saving a new Sale:
Sale sale = new Sale();
sale.setPromotionId(1);
// ...
SaleDetails saleDetail1 = new SaleDetails();
saleDetail1.setProductId(2);
// set other fields except sale
sale.addSaleDetail(saleDetail1);
SaleDetails saleDetail2 = new SaleDetails();
saleDetail2.setProductId(3);
// set other fields except sale
sale.addSaleDetail(saleDetail2);
entityManager.persist(sale);
Answered By - SternK