Мне нужно создать таблицу со многими ко многим с дополнительным столбцом в JPA.
Я использую: openjpa-maven-plugin
для улучшения во время сборки, openjpa 2.2.0
, hsql file db
, testng + spring
У меня есть три таблицы: Analysis
, localizedAnalysisName
(объединяемая таблица) и Locale
Мой код:
@Entity
@Table(name = "analysis", catalog = "testdb")
public class Analysis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "analysis_id", unique = true, nullable = false)
private int analysisId;
@OneToMany(mappedBy = "analysis", cascade = CascadeType.PERSIST)
private List<LocalizedAnalysisName> localizedNames = new ArrayList<LocalizedAnalysisName>();
public void addLocalizedName(Locale locale, String localized_text) {
LocalizedAnalysisName localizedAnalysisName = new LocalizedAnalysisName();
localizedAnalysisName.setLocale(locale);
localizedAnalysisName.setAnalysis(Analysis.this);
localizedAnalysisName.setLocaleId(locale.getLocaleId());
localizedAnalysisName.setAnalysisId(this.getAnalysisId());
localizedAnalysisName.setLocalizedText(localized_text);
localizedNames.add(localizedAnalysisName);
}
...
@Entity
@Table(name = "locale", catalog = "testdb")
public class Locale implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "locale_id", unique = true, nullable = false)
private int localeId;
@Column(name = "language", length = 200)
private String language;
@Column(name = "country", length = 200)
private String country;
@Column(name = "variant", length = 200)
private String variant;
...
@Entity
@Table(name = "localized_analysis_name", catalog = "testdb")
@IdClass(LocalizedAnalysisNameId.class)
public class LocalizedAnalysisName implements Serializable {
@Id
private int analysis_id;
@Id
private int locale_id;
@Column(name = "localized_text", nullable = false, length = 200)
private String localizedText;
@ManyToOne
@PrimaryKeyJoinColumn(name="locale_id", referencedColumnName="locale_id")
private Locale locale;
@ManyToOne
@PrimaryKeyJoinColumn(name="analysis_id", referencedColumnName="analysis_id")
private Analysis analysis;
public LocalizedAnalysisName() {
}
public String getLocalizedText() {
return localizedText;
}
public void setLocalizedText(String localizedText) {
this.localizedText = localizedText;
}
public Locale getLocale() {
return locale;
}
public Analysis getAnalysis() {
return analysis;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public void setAnalysis(Analysis analysis) {
this.analysis = analysis;
}
public void setAnalysisId(int analysis_id) {
this.analysis_id = analysis_id;
}
public void setLocaleId(int locale_id) {
this.locale_id = locale_id;
}
@Embeddable
public class LocalizedAnalysisNameId implements Serializable {
private int analysis_id;
private int locale_id;
public LocalizedAnalysisNameId() {
}
public int getAnalysisId() {
return analysis_id;
}
public void setAnalysisId(int analysis_id) {
this.analysis_id = analysis_id;
}
public int getLocaleId() {
return locale_id;
}
public void setLocaleId(int locale_id) {
this.locale_id = locale_id;
}
public int hashCode() {
return analysis_id + locale_id;
}
public boolean equals(Object object) {
if (object instanceof LocalizedAnalysisNameId) {
LocalizedAnalysisNameId otherId = (LocalizedAnalysisNameId) object;
return (otherId.analysis_id == this.analysis_id) && (otherId.locale_id == this.locale_id);
}
return false;
}
БД:
CREATE TABLE locale (
locale_id integer NOT NULL IDENTITY,
language varchar(200) DEFAULT NULL,
country varchar(200) DEFAULT NULL,
variant varchar(200) DEFAULT NULL,
PRIMARY KEY (locale_id)
);
CREATE TABLE analysis (
analysis_id integer NOT NULL IDENTITY,
source_id varchar(500) DEFAULT NULL,
locale_id integer,
PRIMARY KEY (analysis_id),
FOREIGN KEY (locale_id)
REFERENCES locale (locale_id)
);
CREATE TABLE localized_analysis_name (
analysis_id integer,
locale_id integer,
localized_text varchar(200) DEFAULT NULL,
PRIMARY KEY (analysis_id, locale_id),
FOREIGN KEY (analysis_id)
REFERENCES analysis (analysis_id),
FOREIGN KEY (locale_id)
REFERENCES locale (locale_id)
);
INSERT INTO LOCALE VALUES(0,'en','US','');
INSERT INTO LOCALE VALUES(1,'de','DE','');
А вот мой фрагмент метода тестирования в testng:
@Test(enabled = true)
@Rollback(false)
public void testSave() {
Analysis analysis = new Analysis();
Locale locale = localeDao.findById(0);
analysis.addLocalizedName(locale,"localized text");
analysisDao.save(analysis);
}
Когда я собираюсь, тест не проходит
invalidstateexception:
Caused by: <openjpa-2.2.0-r422266:1244990 fatal user error> org.apache.openjpa.persistence.InvalidStateException:
Attempt to set column "localized_analysis_name.analysis_id" to two different values: (class java.lang.Long)"0", (class java.lang.Integer)"40"
This can occur when you fail to set both sides of a
two-sided relation between objects, or when you map
different fields to the same column, but you do not
keep the values of these fields in synch.
ПОЖАЛУЙСТА, кто-нибудь может сказать мне, как это сделать правильно?Спасибо.