[英]Hibernate/Spring: Not-null property references a null or transient value
我正在使用Java中的Hibernate,Spring和GWT開發一個應用程序。 我在Hibernate(使用JBoss Developer Studio)下使用逆向工程從現有的MySQL數據庫中獲取POJO和配置文件。 這是一個非常簡單的數據庫,只有兩個實體:國家和公民。 他們之間有OneToMany關系。
這是代碼:
app入口點:
...
Country country = new Country();
country.setName("NameOfCountry"+i);
country.setPopulation(10000);
Citizen ctz = new Citizen();
ctz.setName("John");
ctz.setSurname("Smith");
ctz.setCountry(country);
country.getCitizens().add(ctz);
service.saveCitizen(ctz, new AsyncCallback<Boolean>(){
@Override
public void onFailure(Throwable caught) {
System.out.println("Problem saving citizen");
}
@Override
public void onSuccess(Boolean result) {
System.out.println("Citizen successfully saved");
}
});
service.saveCountry(country, new AsyncCallback<Boolean>(){
@Override
public void onFailure(Throwable caught) {
System.out.println("Problem saving country");
}
@Override
public void onSuccess(Boolean result) {
System.out.println("Country successfully saved");
}
});
...
- service為服務器提供簡單的GWT-RPC調用
服務器上的服務:
@Service("componentService")
public class ComponentServiceImpl implements ComponentService{
@Autowired
private CountryDAO daoCnt;
@Autowired
private CitizenDAO daoCtz;
@Transactional(readOnly=false)
@Override
public boolean saveCitizen(Citizen citizen) {
daoCtz.saveOrUpdate(citizen);
return true;
}
@Transactional(readOnly=false)
@Override
public boolean saveCountry(Country country) {
daoCnt.saveOrUpdate(country);
return true;
}
}
現在SpringDAOs:
CitizenDAO:
@Repository
public class CitizenDAO {
...
public void saveOrUpdate(Citizen citizen){
sessionFactory.getCurrentSession().saveOrUpdate(citizen);
}
...
CountryDAO:
@Repository
public class CountryDAO {
...
public void saveOrUpdate(Country country){
sessionFactory.getCurrentSession().saveOrUpdate(country);
}
...
最后
Citizen.hbm.xml:
<hibernate-mapping>
<class name="sk.jakub.mod.shared.model.Citizen" table="citizen" catalog="modeldb">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<many-to-one name="country" class="sk.jakub.mod.shared.model.Country" fetch="select">
<column name="Country_id" not-null="true" />
</many-to-one>
<property name="name" type="string">
<column name="name" length="45" not-null="true" />
</property>
<property name="surname" type="string">
<column name="surname" length="45" not-null="true" />
</property>
</class>
</hibernate-mapping>
Country.hbm.xml:
<hibernate-mapping>
<class name="sk.jakub.mod.shared.model.Country" table="country" catalog="modeldb">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="45" not-null="true" />
</property>
<property name="population" type="int">
<column name="population" not-null="true" />
</property>
<set name="citizens" table="citizen" inverse="true" lazy="true" fetch="select">
<key>
<column name="Country_id" not-null="true" />
</key>
<one-to-many class="sk.jakub.mod.shared.model.Citizen" />
</set>
</class>
</hibernate-mapping>
我沒有列出Citizen.java和Country.java,因為它們只是基本的POJO(如果需要我會提供它們)。
當我啟動我的應用程序並且我想將數據保存到數據庫時,我獲得以下錯誤:
org.hibernate.PropertyValueException: not-null property references a null or transient value: sk.jakub.mod.shared.model.Citizen.country
我無法弄清楚問題出在哪里。 我也嘗試了而不是saveOrUpdate方法,persist方法。 或者還要更改保存到數據庫的順序。 似乎沒什么用。
非常感謝您的幫助:)如果需要,我可以從我的應用程序發布更多代碼。
編輯:Citizen.java的代碼:
public class Citizen implements java.io.Serializable {
private static final long serialVersionUID = -3102863479088406293L;
private Integer id;
private Country country;
private String name;
private String surname;
public Citizen() {
}
public Citizen(Country country, String name, String surname) {
this.country = country;
this.name = name;
this.surname = surname;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Stat getCountry() {
return this.country;
}
public void setCountry(Country country) {
this.country = country;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return this.surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
Country.java:
public class Country implements java.io.Serializable {
private static final long serialVersionUID = -4085805854508658303L;
private Integer id;
private String name;
private int population;
private Set<Citizen> citizens = new HashSet<Citizen>();
public Country() {
}
public Country(String name, int population) {
this.name = name;
this.population = population;
}
public Country(String name, int population, Set<Citizen> citizens) {
this.name = name;
this.population = population;
this.citizens = citizens;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return this.population;
}
public void setPopulation(int population) {
this.population = population;
}
public Set<Citizen> getCitizens() {
return this.citizens;
}
public void setCitizens(Set<Citizen> citizens) {
this.citizens = citizens;
}
}
此外,我手動檢查了數據庫,保存了國家,但公民卻沒有。
在創建國家之前,我看到你正在創建一個公民。 此外,兩個服務調用都應該在同一個事務中,以使整個操作成為原子操作。 COUNTRY_ID似乎是我相信的自我生成的ID。 因此,一旦您創建了國家/地區,您就可以將其附加到公民,但是您調用堆棧顯示您正在創建一個擁有Country對象且沒有id的公民。 這只是我的猜測。 您可以嘗試將兩個呼叫置於同一個交易下,也可以嘗試創建一個國家/地區並將該國家/地區實例附加到Citizen。
請檢查您是否正確實現了equals,hashcode和compareTo(如果適用)方法。 我最近遇到了這個問題,並通過適當的實施來解決這個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.