Diego
Diego

Reputation: 11

JPA repository org.hibernate.LazyInitializationException: could not initialize proxy - no Session

I have the following model entities:

@Entity
@Table(name="ABONADO_IMEI")
public class SubscriberImei {
    private SubscriberImeiId id;
    private Terminal terminal;
    private String state;
    private Date date;

    @EmbeddedId
    public SubscriberImeiId getId() {
        return id;
    }
    public void setId(SubscriberImeiId id) {
        this.id = id;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ID_TERMINAL", nullable=false)
    public Terminal getTerminal() {
        return terminal;
    }
    public void setTerminal(Terminal terminal) {
        this.terminal = terminal;
    }

    @Column(name="Estado")
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }

    @Column(name="Fecha")
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }

}

@Entity()
public class Terminal {
    private long id;
    private String code;
    private String brand;
    private String model;
    private String services;
    private Set<SubscriberImei> subscriberImei;

    public Terminal(){

    }

    @Id
    @SequenceGenerator(name="SEQ_TERMINAL_ID", sequenceName="SEQ_TERMINAL_ID",allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_TERMINAL_ID")
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name="Codigo")
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Column(name="Marca")
    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Column(name="Modelo")
    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    @Column(name="Servicios")
    public String getServices() {
        return services;
    }

    public void setServices(String services) {
        this.services = services;
    }

    @OneToMany(fetch=FetchType.LAZY , mappedBy="terminal")
    public Set<SubscriberImei> getSubscriberImei() {
        return subscriberImei;
    }
    public void setSubscriberImei(Set<SubscriberImei> terminals) {
        this.subscriberImei = terminals;
    }   
}

And I'm using the following JPARepository to access it:

public interface SubscriberImeiDao extends JpaRepository<SubscriberImei, SubscriberImeiId>{
    @Query("select u from SubscriberImei u where u.id.snb = ?1 and u.state = ?2")
    SubscriberImei findBySnbAndState(String snb, String state);
}

I need to return the result of findBySnbAndState. This is my code:

@Transactional
public SubscriberImei imeiQuery(String countryId, String snb) {
    SubscriberImei subs = null;

    try{
        this.validateRegion(countryId, snb);

        subs = this.getSubscriberDao().findBySnbAndState(snb,"A");
        subs.getTerminal().getBrand();
        if( subs != null)
            log.info("Subscriber found {}", subs);
        else
            log.info("Subcriber not found!");
    } catch (Exception ex) {
        log.error("Unknown Exception -- ", ex);
    }
    return subs;
}

and I'm getting the mentioned exception at line subs.getTerminal().getBrand(). With this line I'm forcing the lazy relationship to be followed (as was suggested in some other questions). I've also added the following line to my context:

<tx:annotation-driven mode="aspectj"/>

Changing the FetchType to Eager makes it work, but I don't want to do this because is not necessary to always follow the relationship. What am I missing? What am I doing wrong?

Thanks

This is the complete exception stacktrace

 org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at ar.com.redmondsoftware.imeitracking.model.Terminal_$$_jvste48_0.getBrand(Terminal_$$_jvste48_0.java)
    at ar.com.redmondsoftware.imeitrackingbusinesslogic.service.impl.ImeiQueryImpl.imeiQuery(ImeiQueryImpl.java:24)
    at ar.com.redmondsoftware.imeitracking.QueryImei.testQueryImei(QueryImei.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Upvotes: 1

Views: 1144

Answers (1)

Tea Curran
Tea Curran

Reputation: 2983

If you don't want it to eager fetch all the time, you could make a different query that does the eager fetch when needed:

@Query("SELECT u FROM SubscriberImei u LEFT JOIN FETCH u.terminal WHERE u.id.snb = ?1 and u.state = ?2")
SubscriberImei findBySnbAndStateWithTerminal(String snb, String state);

This query is almost always preferred since it will load your data with one query rather than two.

Upvotes: 1

Related Questions