【问题标题】:Spring boot JPA foreign key variable can not read data from mysql dbSpring boot JPA外键变量无法从mysql db读取数据
【发布时间】:2021-11-06 14:35:39
【问题描述】:

我正在为用户和公司创建两个表,多个用户可以属于一个公司,所以它是多对一的关系。但是由于某种原因,company_id 外键变量无法从 Company 表中提取数据(请参见下面的屏幕截图)。我已经在谷歌上搜索了一段时间,但没有找到任何解决方案。非常感谢您的帮助。

UserEntity.java

@Entity(name = "Users")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class UserEntity extends DateAudit {
    private static final long serialVersionUID = -6622427995561357149L;
    
    @Id
    @GeneratedValue()
    @Type(type = "uuid-char")
    @Column(columnDefinition = "VARCHAR(36)", updatable = false, nullable = false)
    private UUID id;
    @Column(unique = true, nullable = false)
    private String username;
    @Column(nullable = false)
    private String password;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id")
    private CompanyEntity company; //can not extract data

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<ItemEntity> safetyPlans;  //but this works
}

CompanyEntity.java

@Entity(name = "Companies")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class CompanyEntity extends DateAudit {
    private static final long serialVersionUID = -6622427995561357151L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String companyId;  

    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<UserEntity> users;
}

UserRepository.java

public interface UserRepository extends CrudRepository<UserEntity, String>, IUserRepository {
    Optional<UserEntity> findOneById(UUID id);
    Optional<UserEntity> findByUsername(String username);
    List<UserEntity> findAll();
}

服务类

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private UserRepository userRepository;

    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override   
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity entity = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException(username));
        return new User(entity.getUsername(), entity.getPassword(), emptyList());
    }
}

公司表

用户表

要读取值时的错误日志(例如 entity.getCompany().getName()):

2021-09-10 17:29:02.747 ERROR 88245 --- [nio-5000-exec-1] c.a.m.auth.JWTAuthenticationFilter       : An internal error occurred while trying to authenticate the user.

org.springframework.security.authentication.InternalAuthenticationServiceException: could not initialize proxy [com.ahurufoundation.management.data.mysql.entity.user.CompanyEntity#1] - no Session
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:108) ~[spring-security-core-5.4.5.jar:5.4.5]
DaoAuthenticationProvider.java:108
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:133) ~[spring-security-core-5.4.5.jar:5.4.5]
AbstractUserDetailsAuthenticationProvider.java:133
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.4.5.jar:5.4.5]
ProviderManager.java:182
    at com.ahurufoundation.management.auth.JWTAuthenticationFilter.attemptAuthentication(JWTAuthenticationFilter.java:41) ~[main/:na]
JWTAuthenticationFilter.java:41
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:222) [spring-security-web-5.4.5.jar:5.4.5]
AbstractAuthenticationProcessingFilter.java:222
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) [spring-security-web-5.4.5.jar:5.4.5]
AbstractAuthenticationProcessingFilter.java:212
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) [spring-security-web-5.4.5.jar:5.4.5]
LogoutFilter.java:103
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) [spring-security-web-5.4.5.jar:5.4.5]
LogoutFilter.java:89
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) [spring-web-5.3.4.jar:5.3.4]
CorsFilter.java:91
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) [spring-security-web-5.4.5.jar:5.4.5]
HeaderWriterFilter.java:90
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) [spring-security-web-5.4.5.jar:5.4.5]
HeaderWriterFilter.java:75
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) [spring-security-web-5.4.5.jar:5.4.5]
SecurityContextPersistenceFilter.java:110
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) [spring-security-web-5.4.5.jar:5.4.5]
SecurityContextPersistenceFilter.java:80
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) [spring-security-web-5.4.5.jar:5.4.5]
WebAsyncManagerIntegrationFilter.java:55
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) [spring-security-web-5.4.5.jar:5.4.5]
WebAsyncManagerIntegrationFilter.java:55
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:336
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) [spring-security-web-5.4.5.jar:5.4.5]
FilterChainProxy.java:211
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) [spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) [spring-web-5.3.4.jar:5.3.4]
DelegatingFilterProxy.java:358
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) [spring-web-5.3.4.jar:5.3.4]
DelegatingFilterProxy.java:271
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:189
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:162
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.3.4.jar:5.3.4]
RequestContextFilter.java:100
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:189
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:162
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.3.4.jar:5.3.4]
FormContentFilter.java:93
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:189
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:162
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.3.4.jar:5.3.4]
CharacterEncodingFilter.java:201
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.4.jar:5.3.4]
OncePerRequestFilter.java:119
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:189
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) [tomcat-embed-core-9.0.43.jar:9.0.43]
ApplicationFilterChain.java:162
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.43.jar:9.0.43]
StandardWrapperValve.java:202
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.43.jar:9.0.43]
StandardContextValve.java:97
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.43.jar:9.0.43]
AuthenticatorBase.java:542
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.43.jar:9.0.43]
StandardHostValve.java:143
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.43.jar:9.0.43]
ErrorReportValve.java:92
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.43.jar:9.0.43]
StandardEngineValve.java:78
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346) [tomcat-embed-core-9.0.43.jar:9.0.43]
CoyoteAdapter.java:346
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.43.jar:9.0.43]
Http11Processor.java:374
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.43.jar:9.0.43]
AbstractProcessorLight.java:65
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887) [tomcat-embed-core-9.0.43.jar:9.0.43]
AbstractProtocol.java:887
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684) [tomcat-embed-core-9.0.43.jar:9.0.43]
NioEndpoint.java:1684
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.43.jar:9.0.43]
SocketProcessorBase.java:49
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
ThreadPoolExecutor.java:1149
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
ThreadPoolExecutor.java:624
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.43.jar:9.0.43]
TaskThread.java:61
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
Thread.java:748
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [com.ahurufoundation.management.data.mysql.entity.user.CompanyEntity#1] - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:170) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
AbstractLazyInitializer.java:170
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:310) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
AbstractLazyInitializer.java:310
    at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
ByteBuddyInterceptor.java:45
    at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
ProxyConfiguration.java:95
    at com.ahurufoundation.management.data.mysql.entity.user.CompanyEntity$HibernateProxy$FN6IM1Ba.getName(Unknown Source) ~[main/:na]
    at com.ahurufoundation.management.auth.UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:33) ~[main/:na]
UserDetailsServiceImpl.java:33
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:93) ~[spring-security-core-5.4.5.jar:5.4.5]
DaoAuthenticationProvider.java:93

【问题讨论】:

  • use text, not images/links, for text--including tables & ERDs。转述或引用其他文本。只提供您需要的东西并将其与您的问题联系起来。仅将图像用于无法表达为文本或增强文本的内容。在图片中包含图例/键和说明。
  • 感谢您的注意,不幸的是,我真的不知道如何在断点处复制变量文本。

标签: mysql spring-boot spring-data-jpa foreign-keys one-to-many


【解决方案1】:

在多对一关系中需要指定引用的列名:

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id", referencedColumnName = "id")
    private CompanyEntity company; //can not extract data

就像您在连接 sql 查询中所做的那样

还要确保每当您尝试从 UserEntity 对象访问公司字段时,您都有一个打开的会话(您处于事务上下文中),因为它是延迟加载的(仅在访问时加载)

请注意,除非您调用:userEntity.getCompany(),否则公司对象将不会被初始化,这就是延迟加载的含义。如果对象被访问,它只会从数据库中加载它。

还有最重要的!您需要在事务上下文中调用userEntity.getCompany(),以便您有一个打开的会话(注释找到用户并使用@Transactional 调用getter 的方法)

示例(错误):

@Override   
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    UserEntity user = userRepository.findByUsername(username);

    // the call to user.getCompany() will throw the same error because as soon as the
    // findByUsername returns the session is closed
    CompanyEntity company = user.getCompany();
}

这个例子会抛出同样的错误,因为一旦 findByUsername 返回会话就关闭了。

示例(好):

@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    UserEntity user = userRepository.findByUsername(username);
    CompanyEntity company = user.getCompany();
}

现在这里的会话只有在离开 loadUserByUsername 方法后才会关闭,所以在里面你会有一个活跃的会话

规则:每次你有一个惰性关联时,如果你想能够加载它,你需要有一个打开的会话(一个会话总是在事务开始时打开)

【讨论】:

  • 你能告诉我们你尝试读取数据的代码吗?
  • 你得到的确切例外是什么?
  • 当我试图读取里面的值时抛出异常。已添加日志。
  • 如果您检查我的回答,您会发现由于延迟加载,您需要在事务中才能执行此操作。 (从答案中阅读我的最后两段)
  • 你说得对,我必须用事务性来注释它。尽管它仍然在调试窗口中显示空值,但它实际上可以通过调用 get...() 来读取变量。也许这更像是一个 IDE 问题(我使用的是 VSCode)。不过非常感谢你这么有耐心。
猜你喜欢
  • 2018-12-16
  • 1970-01-01
  • 2016-10-11
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2016-07-27
  • 2021-08-23
  • 2017-08-11
相关资源
最近更新 更多