You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate多对多映射时出现Bad value for type long错误

Hibernate多对多关联异常及权限集合未加载问题处理

报错信息

Could not extract column [3] from JDBC ResultSet [Bad value for type long : Allows creating new projects] [n/a]

数据库表结构

  • Roles表:id(long类型)、name(String类型)
  • Permissions表:id(long类型)、description(text类型)、permission(String类型)
  • Role_Permission表:关联role_id与permission_id的多对多中间表

实体类代码

Role实体

@Entity
@Table(name = "roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @ManyToMany
    @JoinTable(
        name = "role_permission",
        joinColumns = @JoinColumn(name = "role_id"),
        inverseJoinColumns = @JoinColumn(name = "permission_id")
    )
    private Set<Permission> permissions;

    @OneToMany(mappedBy = "role")
    private Set<User> users;
}

Permission实体

@Entity
@Table(name = "permissions")
public class Permission {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @Column(name = "permission", nullable = false)
    private String permission;

    @Lob
    @Column(name = "description", nullable = true, columnDefinition = "text")
    private String description;

    @ManyToMany(mappedBy = "permissions")
    private Set<Role> roles;
}

User实体关联部分

@ManyToOne
@JoinColumn(name = "role_id", nullable = false)
private Role role;

业务代码片段

User newUser = new User();
newUser.setUsername(registrationDto.getUsername());
newUser.setEmail(registrationDto.getEmail());
newUser.setPassword(bCryptPasswordEncoder.encode(registrationDto.getPassword()));
newUser.setRole(roleRepository.findByName(registrationDto.getRole()));

Role manager = newUser.getRole();

问题现象

  1. 抛出类型转换异常:尝试将字符串Allows creating new projects转为long类型
  2. Role的permissions集合为Hibernate的PersistanceSet代理对象,实际内容为null,设置FetchType.EAGER无效
  3. Role_Permission表数据已正确填充,能正常获取角色关联的用户,但无法加载权限集合

解决方案

1. 修复类型转换异常

报错核心是Hibernate尝试把权限的文本字段(description或permission)转换为long类型,需排查以下点:

  • 确认Role_Permission表结构:必须仅包含role_id和permission_id两个外键列,无多余字段(比如误将permission字段存入中间表)
  • 核对@JoinTable映射:确保inverseJoinColumns指定的是permission_id而非permission/description。当前实体映射逻辑正确,但需注意数据库字段大小写是否与代码一致(部分数据库区分大小写)

2. 修复权限集合未加载问题

PersistanceSet是Hibernate延迟加载的代理集合,即使设置FetchType.EAGER,若Repository查询未关联权限表,依然不会加载数据:

  • 修改roleRepository.findByName方法,添加JOIN FETCH强制关联权限表:
    @Repository
    public interface RoleRepository extends JpaRepository<Role, Long> {
        @Query("SELECT r FROM Role r JOIN FETCH r.permissions WHERE r.name = :name")
        Role findByName(@Param("name") String name);
    }
    
  • Spring Data JPA默认的findByName仅查询Role表字段,不会关联Permissions表,必须显式通过JOIN FETCH加载关联集合

3. 额外注意事项

  • 避免同时使用FetchType.EAGER与未关联查询的Repository方法,两者冲突会导致加载失效
  • 检查事务边界:若在事务外访问permissions集合,会触发LazyInitializationException,需确保操作在事务范围内执行

内容的提问来源于stack exchange,提问作者Martin Dúbravka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 16:07:35