gpt4 book ai didi

java - Spring Boot 和 fetchType=Lazy

转载 作者:太空宇宙 更新时间:2023-11-04 11:52:30 25 4
gpt4 key购买 nike

我的 Spring Boot 应用程序中存在延迟初始化问题。我有一个带有惰性字段 Role 的实体,并且在我的 Spring Security (UserDetailsS​​ervice) 方法中有 LazyInitializationException ,但在 Controller 中没问题。你能向我解释一下 Spring Boot 如何与 fetch = FetchType.LAZY 配合使用吗?为什么它不能在 Spring Security UserDetailsS​​ervice 中工作并且在 Controller 方法中工作?我没有找到任何关于此的指南。谢谢!

Spring 启动:

@SpringBootApplication
public class App {

public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
}

实体:

@Entity
@Table(name = "users")
@Getter
@Setter
@NoArgsConstructor
public class Users {
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "Users_Role", joinColumns = @JoinColumn(name = "User_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles = new HashSet<Role>();
}

我的服务:

@Transactional(readOnly = true)//does not matter
public Users getUserByLogin(String login) {
return usersRepository.findOneByLogin(login);
}

@Transactional(readOnly = true)
public Users getUserByLoginWithRoles(String login) {
Users oneByLogin = usersRepository.findOneByLogin(login);
logger.debug("User was initialize with Roles: " + oneByLogin.getRoles().size()); // force initialize of roles and it works!
return oneByLogin;
}

@Transactional(readOnly = true)//does not matter
public Users testGetUser() {
Users oneByLogin = usersRepository.getOne(1L);
return oneByLogin;
}

@Transactional(readOnly = true)//does not matter
public Users testFindUser() {
Users oneByLogin = usersRepository.findOne(1L);
return oneByLogin;
}

我有 Spring Security UserDetailsS​​ervice:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private Services services;

@Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Users user;
Users userFetchedViaGet = services.testGetUser();
Users userFetchedViaCustomMethod = services.getUserByLogin(login);
Users userFetchedViaFind = services.testFindUser();
Users userFetchedWithRoles = services.getUserByLoginWithRoles(login);
try {
userFetchedViaGet.getRoles().add(new Role("test"));
} catch (Exception e) {
e.printStackTrace();//LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
}
try {
userFetchedViaCustomMethod.getRoles().add(new Role("test"));
} catch (Exception e) {
e.printStackTrace();//LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
}
try {
userFetchedViaFind.getRoles().add(new Role("test")); //LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
} catch (Exception e) {
e.printStackTrace();
}
//some code
}
}

和我的 Controller (所有方法都有效!但是必须发生异常,因为没有 session 和延迟获取类型):

@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
Users userFetchedViaGet = services.testGetUser();
Users userFetchedViaCustomMethod = services.getUserByLogin("ADMIN");
Users userFetchedViaFind = services.testFindUser();
Users userFetchedWithRoles = services.getUserByLoginWithRoles("ADMIN");
try {
userFetchedViaGet.getRoles().add(new Role("test"));
} catch (Exception e) {
e.printStackTrace();
}
try {
userFetchedViaCustomMethod.getRoles().add(new Role("test"));
} catch (Exception e) {
e.printStackTrace();
}
try {
userFetchedViaFind.getRoles().add(new Role("test"));
} catch (Exception e) {
e.printStackTrace();
}
//some code
}

最佳答案

您需要一个事务来包装整个事物 - 在您的外观上 - test() 方法才能使其工作,但这并不是一个好的实践。

解决方法是让您的服务将 api 方法包装在事务中,并返回一个完全加载的对象 - 包含所有子节点。该对象可以是一个从 Users 类构造的简单 bean,从对象构建的 HashMap ,甚至是您想要从其余调用返回的字符串。

关于java - Spring Boot 和 fetchType=Lazy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41676123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com