简体   繁体   中英

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)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM