3

These are the following classes:

@Entity
public class Question {
   @Id
   public Long id;
   public String name;

   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
   @JoinColumn(name = "OWNER_ID", referencedColumnName = "QUES_ID")
   public List<Choice> choices = new ArrayList<>();
}

@Named
@Singleton
public interface QuestionRepository extends CrudRepository<Question , Long> {
    Question findByName(String name);
}

And in the Controller file I have this following File

@Transactional
public Result getQuestion() {
    List<Choices> list = this.questionRepository.findByName("name").choices;
    list.size();
    return ok();
}

list.size() in getQuestion() throws me a LazyInitializationException because there is not open sessions

I know that changing the fetch type to EAGER or using a JPQL query above the function definition in QuestionRepository might solve it, but there are part in my application where those wont help and I would require to lazy fetch.

How would make the entire code in getQuestion() function use a single session/transaction or even better my entire request to take place in an single session/transaction?

Cœur
  • 37,241
  • 25
  • 195
  • 267
AbrahamDaniel
  • 569
  • 2
  • 8
  • 19
  • i think spring can't begin a transaction in `getQuestion` and you're just using the Spring Data's intertanl transactions. – Ali Dehghani Dec 14 '14 at 12:53
  • All `Repository` implementations are Transactional by default. when you're calling `findByName`, spring begins a transcations and when the method returns, transaction commits and since your session is closed, `list.size()` throws `LazyInitializationException`. check play/spring integration.. – Ali Dehghani Dec 14 '14 at 12:56
  • You can refer http://stackoverflow.com/questions/26611173/jpa-jta-transactional-spring-annotation/26615390#26615390 – Harshal Patil Dec 21 '14 at 16:15

1 Answers1

2

From Spring Data JPA reference documentation

4.7.1. Transactional query methods

To allow your query methods to be transactional simply use @Transactional at the repository interface you define.

Example 100. Using @Transactional at query methods

@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {

    List<User> findByLastname(String lastname);

    @Modifying 
    @Transactional
    @Query("delete from User u where u.active = false")  
    void deleteInactiveUsers();
}

Typically you will want the readOnly flag set to true as most of the query methods will only read data. In contrast to that deleteInactiveUsers() makes use of the @Modifying annotation and overrides the transaction configuration. Thus the method will be executed with readOnly flag set to false.

So just add @Transactional annotation to your repository interfaces.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
mavarazy
  • 7,562
  • 1
  • 34
  • 60
  • as mentioned about I want a solution without @Query, a solution that makes the session/transaction available outside the UserRepository. – AbrahamDaniel Dec 15 '14 at 13:39
  • Query is not needed, just add Transactional to interface. – mavarazy Dec 15 '14 at 13:40
  • adding Transactional dint work, getQuestion is a member of my controller class and not repository interface anyway – AbrahamDaniel Dec 15 '14 at 13:43
  • Check propagation of transaction, basically you want your transaction on Repository and method to be with REQUIRED propagation. – mavarazy Dec 15 '14 at 13:46
  • I would love a more elaborate explanation, A link would help me very much. Thank you. – AbrahamDaniel Dec 15 '14 at 14:06
  • 1
    http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html Actually REQUIRED is a default configuration. Check youhave transactions enabled in your Spring configuration (@EnableTransactionManagement or is present)? And leave it just @Transaction in both places. – mavarazy Dec 15 '14 at 14:10