Reputation: 976
I just found a piece of code which looks as follow:
@Transactional
public List<Foo> giveMeFooMatchingSomeConstraints(Long param1, String param2) {
List<Bar> bars = barDao.findBars(param1, param2);
List<Foo> foos = fooDao.findFoosByBarIds(barService.getIds(bars));
return foos;
}
I'm just curious what's the purpose of using @Transactional in case when a method only fetches data and doesn't modify them. Is such an approach like above ok?
Upvotes: 3
Views: 1515
Reputation: 3561
Yes it makes sense when you aren't using Open*InView
and working with lazy relations within your method.
Say we have these entities bounded with one-to-many relation:
@Entity(name = "user")
static class User extends AbstractPersistable<String> {
private String username;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) //by default fetching is lazy
@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_user_roles"))
private Set<Role> roles = new HashSet<>();
public Set<Role> getRoles() {
return this.roles;
}
}
@Entity(name = "role")
static class Role extends AbstractPersistable<String> {
private String name;
private Role() {
}
public Role(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
a repository to access them:
interface UserDao extends JpaRepository<User, String> {}
and a service for some data manipulation - retrieve all users, iterate trough them and grab all the roles:
@Service
static class UserService {
private final UserDao userDao;
UserService(UserDao userDao) {
this.userDao = userDao;
}
@Transactional // <---
public Set<String> findUserRoles() {
final List<User> users = this.userDao.findAll();
return users.stream()
.flatMap(user -> user.roles.stream())
.map(Role::getName)
.collect(Collectors.toSet());
}
}
Remove @Transactional
to see LazyInitializationException
with no Session
message, since nobody have opened it.
To avoid confusions in such cases it is better to explicitly mark transaction as read-only:
@Transactional(readOnly = true)
So reader will know that this method have no intention to modify any data, but transaction (session) is still required.
Upvotes: 3