Reputation: 9827
I'm trying to create a Hibernate entity and then read a one-to-many Collection in the same method/transaction and its always returning empty for the get Collection call. I've tried to use an fetch=FetchType.EAGER
instead of fetch=FetchType.LAZY
and I've also tried a Hibernate flush()
after the car insert and before the car read, but the one-to-many Collection is always empty. If I remove the get Collection call (see getCarList() below) and put it in another method, the Collection is not empty but I would like to keep the insert and read in the same method if possible. I have also tried calling Hibernate.initialize(this.carList)
but still empty. Ideas?
Entity:
@Entity
@Table(name = "car")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "car_type", discriminatorType = DiscriminatorType.STRING)
public class Car {
private Car defaultCar;
private List<Car> carList = new ArrayList<Car>();
@ManyToOne
@JoinColumn(name = "DEFAULT_CAR_ID")
public Car getDefaultCar() {
return defaultCar;
}
public void setDefaultCar(Car defaultCar) {
this.defaultCar = defaultCar;
}
@OneToMany(mappedBy = "defaultCar", fetch=FetchType.LAZY)
public List<Car> getCarList() {
return carList;
}
public void setCarList(List<Car> carList) {
this.carList = carList;
}
@Transient
public void initializeCarList() {
Hibernate.initialize(this.carList);
}
Service Implementation:
public List<Car> saveAndGetDefaultCarList(){
Car car1 = new Car();
carDAO.create(car1);
Car car2 = new Car();
car2.setDefaultCar(car1);
carDAO.create(car2);
List<Car> defaultCarList = car1.getCarList(); //always returning empty List
}
DAO Implementation:
public class CarDAOImpl implements CarDAO {
private DaoFactory daoFactory;
@Override
public Copy create(Car car) {
GenericDao<Car> dao = daoFactory.getDao(Car.class);
return dao.create(car);
}
public void setDaoFactory(DaoFactory daoFactory) {
this.daoFactory = daoFactory;
}
public void setCarDao(CarDAO carDAO) {
this.carDAO = carDAO;
}
}
public class HibernateDaoFactory implements DaoFactory {
private SessionFactory sessionFactory;
private HibernateSessionConfigurer sessionConfigurer;
public <T> GenericDao<T> getDao(Class<T> clazz) {
HibernateDao<T> dao = new HibernateDao<T>(clazz);
dao.setSessionFactory(sessionFactory);
dao.setSessionConfigurer(sessionConfigurer);
return dao;
}
public QueryDao getQueryDao() {
HibernateQueryDao dao = new HibernateQueryDao();
dao.setSessionFactory(sessionFactory);
dao.setSessionConfigurer(sessionConfigurer);
return dao;
}
public void flush() {
sessionFactory.getCurrentSession().flush();
}
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
public void setSessionConfigurer(HibernateSessionConfigurer cfg) {
this.sessionConfigurer = cfg;
}
}
Library Versions:
hibernate-core-4.2.0.final
spring-core-3.2.2.RELEASE.jar
Spring Hibernate Config:
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="create*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
Upvotes: 0
Views: 1203
Reputation: 823
Probably because you have inversed the relation ship from one-to-many side, but has not defined the relationship owner many-to-one side.
You have inversed the relationship. So the One-to-many side does not own the relationship. The owner would be the property "defaultCar"
@OneToMany(mappedBy = "defaultCar", fetch=FetchType.LAZY)
public List<Car> getCarList() {
return carList;
}
But you have not annotated the defaultCar with ManyToOne
Try defining the owner of the relation properly
Upvotes: 0
Reputation: 2597
Your car1 is this same object as it was before car2.setDefaultCar(car1)
, because car2.setDefaultCar(car1);
updates only car2 instance. What you want, is to update car1 state (fetch changes from database), after storing car2 in database.
To do it in one method, you need to flush() session (or commit) and call refresh(car1)
method on car1 instance - it will be recreated from database.
But, there is other approach - first add car2 to car1 collection, and then just persist car1 - this will cause that car2 will be persisted also (when cascade="save-update"
is set).
Upvotes: 1