I have a schema that includes two polymorphic entity classes using the join strategy. When I call EntityManager.refresh on one of the subclasses a lazy collection in its superclass fails to work. Specifically, when I try to get a record from that collection, I get this exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.hibernate.bugs.Company.people: could not initialize proxy - no Session
The failure happens whether or not I include CascadeType.REFRESH on the collection.
Here is a picture of the schema:
!Hibernate_refresh_lazy.png|width=721,height=331!
Here is the essential source code:
{noformat}@Entity @Inheritance(strategy= InheritanceType.JOINED) @DiscriminatorColumn(name="CompanyType", discriminatorType= DiscriminatorType.INTEGER) public abstract class ComputerSystem { @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private long id;
@ManyToOne @JoinColumn(name = "OWNER_ID", foreignKey = @ForeignKey()) protected Company owner = null;
public void setOwner(Company owner) { this.owner = owner; } }
@Entity @DiscriminatorValue("2") public class ManufacturerComputerSystem extends ComputerSystem { }
@Entity @Inheritance(strategy= InheritanceType.JOINED) @DiscriminatorColumn(name="CompanyType", discriminatorType= DiscriminatorType.INTEGER) public abstract class Company { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) protected long id;
@OneToMany(mappedBy="company", orphanRemoval=true, cascade=CascadeType.ALL, fetch=FetchType.LAZY) private List<Person> people = new ArrayList<>();
public List<Person> getPeople() { return people; }
public void addPerson(Person person) { people.add(person); person.setCompany(this); } }
@Entity @DiscriminatorValue("1") public class ManufacturerCompany extends Company { @OneToOne(orphanRemoval=true, cascade=CascadeType.ALL, fetch=FetchType.LAZY) @JoinColumn(name = "COMPUTERSYSTEM_ID", foreignKey = @ForeignKey()) private ManufacturerComputerSystem computerSystem;
public void setComputerSystem(ManufacturerComputerSystem computerSystem) { this.computerSystem = computerSystem; computerSystem.setOwner(this); } }
@Entity public class Person { @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private long id;
private String firstName;
@ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name = "COMPANY_ID", foreignKey = @ForeignKey()) private Company company;
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getFirstName() { return firstName; }
public void setCompany(Company company) { this.company = company; } }
public class JPAUnitTestCase { @Before public void init() { // Details omitted for brevity }
@Test public void refresh_test() { EntityManager entityManager = entityManagerFactory.createEntityManager();
ManufacturerCompany manufacturerCompany = entityManager.find(ManufacturerCompany.class, 1L); entityManager.refresh(manufacturerCompany); List<Person> people = manufacturerCompany.getPeople(); Person person1 = people.get(0); // <-- This is where it fails. String newFirstName = "name1".equals(person1.getFirstName()) ? "name2" : "name1"; entityManager.getTransaction().begin(); person1.setFirstName(newFirstName); entityManager.getTransaction().commit(); assertEquals("Get latest name", newFirstName, person1.getFirstName()); } }{noformat}
Here is a project that reproduces the problem (it is also attached) : [https://github.com/robscala/Hibernate_lazy_load_collection_fails|https://github.com/robscala/Hibernate_lazy_load_collection_fails|smart-link] |
|