java Hibernate/Spring:非空属性引用空值或瞬态值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12482169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate/Spring: Not-null property references a null or transient value
提问by Reshi
I'm developing an application using Hibernate, Spring and GWT in Java. I used reverse engineering under Hibernate (JBoss Developer Studio used) to obtain POJOs and configuration files from an existing MySQL database. It's very simple database with only two entities: Country and Citizen. They have OneToMany relationship between.
我正在使用 Java 中的 Hibernate、Spring 和 GWT 开发应用程序。我在 Hibernate(使用 JBoss Developer Studio)下使用逆向工程从现有的 MySQL 数据库中获取 POJO 和配置文件。这是一个非常简单的数据库,只有两个实体:国家和公民。它们之间有 OneToMany 关系。
Here is the code:
这是代码:
app entry point:
应用入口点:
...
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 provides simple GWT-RPC call to server
-- 服务向服务器提供简单的 GWT-RPC 调用
Service on server:
服务器上的服务:
@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;
}
}
Now SpringDAOs:
现在 SpringDAO:
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);
}
...
Finally
最后
Citizen.hbm.xml:
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:
国家.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>
I havent listed Citizen.java and Country.java because they are only basic POJOs (if necessary I'll provide them).
我没有列出 Citizen.java 和 Country.java 因为它们只是基本的 POJO(如果需要,我会提供它们)。
When I launch my app and I want to save my data into database I obtain following error:
当我启动我的应用程序并且我想将我的数据保存到数据库中时,我收到以下错误:
org.hibernate.PropertyValueException: not-null property references a null or transient value: sk.jakub.mod.shared.model.Citizen.country
I can't figure out where is the problem. I was trying also instead of saveOrUpdate method, persist method. Or also to change the order of saving into database. Nothing seemed to work.
我无法弄清楚问题出在哪里。我也在尝试,而不是 saveOrUpdate 方法,persist 方法。或者也可以更改保存到数据库的顺序。似乎没有任何效果。
Thank you very much for help :) If needed, I can post more code from my application.
非常感谢您的帮助 :) 如果需要,我可以从我的应用程序中发布更多代码。
EDIT: code for Citizen.java:
编辑: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:
国家.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;
}
}
Furthermore, I've checked the database manually and Country is saved but citizen is not.
此外,我已经手动检查了数据库,国家被保存,但公民没有。
回答by raddykrish
I am seeing that you are creating a Citizen before you create a country. Also both the service calls should be in same transaction for the whole operation to be atomic. The COUNTRY_ID seems to be a self generated id i believe. So once you create the country you can attach that to a citizen but you call stack shows you are creating a citizen which has a Country object which doesnt have an id. This is just my guess. You can try putting both the calls under same transaction and also try creating a Country and attach that country instance to the Citizen.
我看到您在创建国家之前先创建公民。此外,两个服务调用都应该在同一个事务中,整个操作都是原子的。我相信 COUNTRY_ID 似乎是一个自生成的 ID。因此,一旦您创建了国家,您就可以将其附加到公民,但您调用堆栈显示您正在创建一个公民,该公民具有一个没有 id 的 Country 对象。这只是我的猜测。您可以尝试将两个调用置于同一事务下,也可以尝试创建一个国家并将该国家/地区实例附加到 Citizen。
回答by yourganesan
Please check if you have implemented the equals, hashcode and compareTo (if applicable) methods properly. I have recently faced this problem and resolved it by proper implemetation of these.
请检查您是否正确实现了 equals、hashcode 和 compareTo(如果适用)方法。我最近遇到了这个问题,并通过适当地实现这些问题来解决它。