Hibernate是个强大,开发效率高的开源框架—这已是行业所公认的事实.
对于初接触Hibernate的我来说,却因为他强大的封装能力,出现问题时,完成不知从何处下手.
信手写了个Person类:
package com.wls.domain;
import java.util.Date;
public class Person {
private Integer personId;
private String name;
private Date birthday;
private Address address;
public Person(){
}
public Integer getPersonId() {
return personId;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Person [personId=" + personId + ", name=" + name
+ ", birthday=" + birthday + ", address=" + address + "]";
}
}
再写一个Address类:
package com.wls.domain;
import java.util.Date;
public class Address {
private Integer addressId;
private String addressDetail;
private Person person;
public Address(){
}
public Address(String addressDetail){
this.addressDetail=addressDetail;
}
public Integer getAddressId() {
return addressId;
}
public void setAddressId(Integer addressId) {
this.addressId = addressId;
}
public String getAddressDetail() {
return addressDetail;
}
public void setAddressDetail(String addressDetail) {
this.addressDetail = addressDetail;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "Address [addressId=" + addressId + ", addressDetail="
+ addressDetail +"]";
}
}
这个两Pojo对应的映射文件为:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.wls.domain">
<class name="Person">
<id name="personId" type="java.lang.Integer">
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String"></property>
<property name="birthday" type="java.util.Date"></property>
<one-to-one name="address" class="Address" property-ref="addressId" cascade="save-update" >
</one-to-one>
</class>
<class name="Address">
<id name="addressId" type="java.lang.Integer">
<generator class="native"></generator>
</id>
<property name="addressDetail" type="java.lang.String"></property>
<many-to-one name="person" class="Person" unique="true" not-null="true"></many-to-one>
</class>
</hibernate-mapping>
前奏写好了,之后写了个DAO--UserManagerDao:
package com.wls.dao;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.wls.domain.Address;
import com.wls.domain.Person;
public class UserManagerDao {
private SessionFactory sessionFactory;
private Session session;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
if(session==null){
session=sessionFactory.openSession();
}
return session;
}
public Integer addAddress(Address address){
Transaction tx=getSession().beginTransaction();
Integer AddressId=(Integer)getSession().save(address);
tx.commit();
return AddressId;
}
public Integer addPerson(Person person){
Transaction tx=getSession().beginTransaction();
Integer personId=(Integer)getSession().save(person);
tx.commit();
return personId;
}
public Person getPerson(Integer personId){
Transaction tx=getSession().beginTransaction();
Person person=(Person) getSession().get(Person.class, personId);
tx.commit();
return person;
}
public List<Person> getAllPerons(){
Transaction tx=getSession().beginTransaction();
Query query=getSession().createQuery("select person from Person person");
if(query==null){
System.out.println("query is null");
return new ArrayList<Person>();
}else{
System.out.println("query is not null");
}
List<Person> persons=query.list();
tx.commit();
return persons;
}
public List<Address> getAllAddresses(){
Transaction tx=getSession().beginTransaction();
Query query=getSession().createQuery("select person from Address person");
if(query==null){
System.out.println("query is null");
return new ArrayList<Address>();
}else{
System.out.println("query is not null");
}
List<Address> addresses=query.list();
tx.commit();
return addresses;
}
}
最后,就只差用于测试的类了—MainTest:
package com.wls.test;
import java.util.Date;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wls.dao.UserManagerDao;
import com.wls.domain.Address;
import com.wls.domain.Person;
public class MainTest {
public static void main(String[] args){
System.out.println("Main Method!");
ApplicationContext context=new ClassPathXmlApplicationContext("SpringConfig.xml");
UserManagerDao userManagerDao=context.getBean("userManagerDao", UserManagerDao.class);
Address address=new Address("广东广州");
Person person=new Person();
person.setBirthday(new Date());
person.setName("佢顺");
address.setPerson(person);
userManagerDao.addAddress(address);
System.out.println("Main Mehtod End!");
}
}
随手点了下运行按钮,却出现了如下错误:
Hibernate: select hibernate_sequence.nextval from dual
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.wls.domain.Person
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:456)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:265)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:275)
at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:295)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3403)
at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:520)
at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:230)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.wls.dao.UserManagerDao.addAddress(UserManagerDao.java:33)
at com.wls.test.MainTest.main(MainTest.java:33)
再次确认映射文件,我已经写了cascade=save-update为什么会出现如此问题?
思考了半个小时,头疼,放弃了.
然后改了一下MainTest:
package com.wls.test;
import java.util.Date;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wls.dao.UserManagerDao;
import com.wls.domain.Address;
import com.wls.domain.Person;
public class MainTest {
public static void main(String[] args){
System.out.println("Main Method!");
ApplicationContext context=new ClassPathXmlApplicationContext("SpringConfig.xml");
UserManagerDao userManagerDao=context.getBean("userManagerDao", UserManagerDao.class);
Address address=new Address("广东广州");
Person person=new Person();
person.setBirthday(new Date());
person.setName("佢顺");
Integer personId=userManagerDao.addPerson(person);
address.setPerson(person);
userManagerDao.addAddress(address);
List<Address> addresses=userManagerDao.getAllAddresses();
for(Address a:addresses){
System.out.println(a);
}
System.out.println("Main Mehtod End!");
}
}
运行结果如春风吹过,舒畅的感觉:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into Person (name, birthday, personId) values (?, ?, ?)
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into Address (addressDetail, person, addressId) values (?, ?, ?)
query is not null
Hibernate: select address0_.addressId as addressId1_, address0_.addressDetail as addressD2_1_, address0_.person as person1_ from Address address0_
Address [addressId=42, addressDetail=广东广州]
Address [addressId=44, addressDetail=广东广州]
Address [addressId=46, addressDetail=广东广州]
Address [addressId=48, addressDetail=广东广州]
Address [addressId=50, addressDetail=广东广州]
Address [addressId=52, addressDetail=广东广州]
Address [addressId=55, addressDetail=广东广州]
Main Mehtod End!
再改MainTest:
package com.wls.test;
import java.util.Date;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wls.dao.UserManagerDao;
import com.wls.domain.Address;
import com.wls.domain.Person;
public class MainTest {
public static void main(String[] args){
System.out.println("Main Method!");
ApplicationContext context=new ClassPathXmlApplicationContext("SpringConfig.xml");
UserManagerDao userManagerDao=context.getBean("userManagerDao", UserManagerDao.class);
Address address=new Address("广东广州");
Person person=new Person();
person.setBirthday(new Date());
person.setName("佢顺");
Integer personId=userManagerDao.addPerson(person);
address.setPerson(person);
userManagerDao.addAddress(address);
List<Person> persons=userManagerDao.getAllPerons();
for(Person p:persons){
System.out.println(p);
}
System.out.println("Main Mehtod End!");
}
}
想不到冬天来得这么快:
Exception in thread "main" java.lang.NullPointerException
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:1791)
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:681)
at org.hibernate.type.EntityType.resolve(EntityType.java:441)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at com.wls.dao.UserManagerDao.getAllPerons(UserManagerDao.java:60)
at com.wls.test.MainTest.main(MainTest.java:35)
想了半天,还是不明白为什么是java.lang.NullPointerException想经过测试, com.wls.dao.UserManagerDao.getAllPerons(UserManagerDao.java:60)中的query并不是null.看来问题是出在Peson对象上面了.
那是不是说我不用Address的话永远就取不了Peson了.
解决方案在哪里,又是仰望星空半天.
嗯,解决方案不在今天.