Spring中User类含实体子类时JWT认证失败问题求助
问题解决:JOINED继承下标注子类@Entity导致JWT认证失效的类型转换异常
问题根源
使用Hibernate的InheritanceType.JOINED继承策略时,若未显式指定鉴别器(Discriminator),Hibernate会自动生成基于Case语句的鉴别器映射。在部分Hibernate版本(尤其是6.x)中,这种自动生成的实现存在bug,导致查询用户时抛出CaseStatementDiscriminatorMappingImpl$1 cannot be cast to SqlSelection类型转换异常,进而使UserDetailsService无法正常加载用户,JWT认证流程中断。
解决方案
通过显式配置鉴别器列和子类对应的鉴别器值,替代Hibernate自动生成的Case语句鉴别器,修复映射错误。
1. 修改父类User,添加鉴别器列配置
@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "user_table") @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "user_type", discriminatorType = DiscriminatorType.STRING) // 显式指定鉴别器列 public class User{ @Id private UUID user_id; @Column(name = "username",unique = true,nullable = false) private String username; @Column(name = "password",nullable = false) private String password; }
2. 修改子类Customer,指定鉴别器值
@NoArgsConstructor @AllArgsConstructor @ToString @Entity(name = "customer") @DiscriminatorValue("CUSTOMER") // 指定该子类对应的鉴别器值 public class Customer extends User{ @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; }
3. 确保Repository查询正确处理继承关系
确认UserRepository的findByUsername方法是基于父类User的查询,示例:
@Repository public interface UserRepository extends JpaRepository<User, UUID> { User findByUsername(String username); }
原理说明
显式配置鉴别器后,Hibernate会在父表user_table中新增user_type列,存储每个用户对应的子类类型标识(如CUSTOMER)。查询时,Hibernate通过该列明确区分不同子类,避免了自动生成Case语句带来的映射冲突,从而修复类型转换异常,让UserDetailsService能正常加载用户数据,JWT认证流程恢复正常。
内容的提问来源于stack exchange,提问作者Abd El Rahman Tamer
相关产品推荐
相关产品推荐

