执行关联角色权限的JPQL查询时触发Hibernate空指针异常
问题:JPQL查询关联权限时抛出NullPointerException
执行JPQL查询获取特定RoleEntity关联的PermissionEntity时,抛出如下空指针异常:
java.lang.NullPointerException: Cannot invoke "org.hibernate.persister.entity.DiscriminatorType.getJdbcJavaType()" because "this.discriminatorType" is null
问题代码
查询语句:
@Query("SELECT PermissionEntity " + "FROM RolePermissionEntity rolePermission " + "JOIN PermissionEntity permission " + "WHERE rolePermission.role = :role") List<PermissionEntity> findPermissionsByRoleId(@Param("role") RoleEntity role);
实体模型
RoleEntity
@Entity @Table( name = "roles", indexes = { @Index(name = "role_name_unique", columnList = "name", unique = true) } ) /* Lombok注解省略 */ public class RoleEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String name; @Transient private List<PermissionEntity> permissions; }
PermissionEntity
@Entity @Table( name = "permissions", indexes = { @Index(name = "permission_name_unique", columnList = "name", unique = true) } ) /* Lombok注解省略 */ public class PermissionEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String name; }
RolePermissionEntity
@Entity @Table( name = "role_permissions" ) /* Lombok注解省略 */ public class RolePermissionEntity { @EmbeddedId private RolePermissionId id; @MapsId("roleId") @ManyToOne private RoleEntity role; @MapsId("permissionId") @ManyToOne private PermissionEntity permission; }
RolePermissionId
@Embeddable /* Lombok注解省略 */ public class RolePermissionId implements Serializable { private Integer roleId; private Integer permissionId; }
环境
Spring Boot 3.0.1 + Spring Data JPA + Hibernate
解决方案
1. 修正JPQL查询语句
原查询存在两个关键错误:
- SELECT子句误用实体类名
PermissionEntity,应改为关联的别名permission - JOIN子句直接关联实体类,未通过中间表
RolePermissionEntity的关联属性,需改为通过rolePermission.permission建立关联
修正后的查询:
@Query("SELECT permission " + "FROM RolePermissionEntity rolePermission " + "JOIN rolePermission.permission permission " + "WHERE rolePermission.role = :role") List<PermissionEntity> findPermissionsByRoleId(@Param("role") RoleEntity role);
2. 异常原因说明
该空指针异常源于错误的JPQL关联写法:直接关联PermissionEntity而非通过中间表的permission属性,会导致Hibernate解析实体元数据时误判继承结构(尽管当前实体无继承关系),进而触发鉴别器类型的空指针问题。修正关联方式后,Hibernate可正确识别实体间的关联逻辑,异常即可解决。
可选优化:简化实体关联
若业务允许,可在RoleEntity中直接建立@ManyToMany关联,省略手动维护中间表实体的操作:
@Entity @Table(name = "roles") public class RoleEntity { // 其他属性不变 @ManyToMany @JoinTable( name = "role_permissions", joinColumns = @JoinColumn(name = "roleId"), inverseJoinColumns = @JoinColumn(name = "permissionId") ) private List<PermissionEntity> permissions; }
此时可直接使用Spring Data JPA的默认查询方法,或编写更简洁的JPQL语句,无需手动操作中间表实体。
内容的提问来源于stack exchange,提问作者Maxime Esnol
相关产品推荐
相关产品推荐

