У меня есть две сущности: продажа и продажа_детали. У одной продажи будет много sale_details, но каждая sale_detail принадлежит только одной продаже, мой текущий код дает мне повторяющийся столбец в сопоставлении для ошибки объекта.
Распродажа:
@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;
}
Распродажа_детали:
@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;
}
Структуры таблиц:
Я пытаюсь сделать отношения двунаправленными, что я здесь делаю неправильно? Насколько я понимаю, владеющая сторона отношения — это отношение «многие к одному» в объекте sale_details, а mappedby в объекте продажи просто ссылается на то, что на обратной стороне уже есть сопоставление?
Полная трассировка стека ошибок:
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")
Я бы посоветовал вам следовать соглашениям об именах Java. Согласно этим ролям:
Классы: Имена классов должны быть существительными в смешанном регистре с заглавной первой буквой каждого внутреннего слова.
Переменные: за исключением переменных, все экземпляры, классы и константы классов указаны в смешанном регистре с первой буквой в нижнем регистре. Внутренние слова начинаются с заглавных букв.
Итак, я бы посоветовал вам исправить ваше сопоставление следующим образом:
@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
}
Значение в mappedBy
относится к имени поля другой стороны ассоциации.
Вы можете не использовать referencedColumnName
, если внешний ключ ссылается на поле первичного ключа целевого объекта.
И пример создания и сохранения новой продажи:
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);
Похоже, вы не предоставили полное сопоставление, потому что я не вижу из предоставленного сопоставления, где столбец saleid_fk
дублируется.
хм, так вы хотите увидеть весь код? поскольку он длиннее этого, я просто сократил его, чтобы вопрос было легче читать.
я выложил полный маппинг
Что ж, как было предложено в сообщении об ошибке исключения, вы можете добавить @Column(name = "saleid_fk", insertable = false, updatable = false)
или @JoinColumn(name = "saleid_fk", insertable = false, updatable = false)
, но я бы не советовал этого делать. Я бы предложил вообще удалить @Column(name = "saleid_fk")
и установить все связанные друг с другом сущности через сеттеры. И обратите внимание, когда вы используете двунаправленную связь, обе стороны ассоциации должны быть синхронизированы.
Я удалил @Column (name = "saleid_fk"), и у меня уже есть геттеры и сеттеры для всех переменных столбцов, ошибка все еще сохраняется. Как удаление @Column(name = "saleid_fk") должно было решить ошибку? Я не понимаю, как это должно что-то исправить.
Пожалуйста, покажите, как вы сохраняете свои объекты.
У меня нет настроенных операций с базой данных, я даже не могу успешно развернуть программу из-за этой ошибки.
Теперь работает! Большое спасибо. Моя проблема заключалась в том, что я дважды установил saleid_fk, который вы исправили. спасибооуу
Хорошо, я внес изменения, но та же ошибка все еще остается. Я не думаю, что это синтаксическая ошибка.