1

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)

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

It works, great idea!! Thanks. But do you know why the @Transactional aproach doesn't work?
I couldn't say without seeing more of your code. Are you using spring Transactional rather than javax? How is the repository injected?
We are using "org.springframework.transaction.annotation.Transactional" and this is the way that we are injecting the repository: "<jpa:repositories base-package="ar.com.redmondsoftware.imeitracking.dao" />"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.