Spring Boot(JPA CrudRepository)自动生成SQL错误排查求助
问题分析与解决方案
你遇到的这个错误确实是JPA关联关系配置不当导致的,咱们一步步来排查修复:
问题根源
你的双向一对多关联(Album -> Song)没有正确配置映射规则:
Album类的@OneToMany没有指定关联的维护端(mappedBy)Song类的@ManyToOne没有明确指定数据库中对应的外键列
JPA默认会为未配置的关联生成一个外键列,命名规则是关联实体属性名+下划线+关联实体主键名,也就是album_album_id,但你的songs表实际存在的外键是album_id,因此出现了列不存在的错误。
修复步骤
1. 修正Song类的@ManyToOne关联
在Song的album属性上添加@JoinColumn,明确指定关联的数据库列是album_id,同时可以移除冗余的songAlbumId字段(因为JPA会通过关联自动维护外键):
@Entity @Table(name = "songs", schema = "dbo") public class Song { @Id @GeneratedValue @Column(name = "song_id") private Integer songId; @Column(name = "song_name") private String songName; @Column(name = "song_duration") private String songDuration; // 修正关联配置 @ManyToOne @JoinColumn(name = "album_id") // 指定数据库中的外键列名 private Album album; // getter和setter方法 // 移除songAlbumId相关的getter/setter public Integer getSongId() { return songId; } public void setSongId(Integer songId) { this.songId = songId; } public String getSongName() { return songName; } public void setSongName(String songName) { this.songName = songName; } public String getSongDuration() { return songDuration; } public void setSongDuration(String songDuration) { this.songDuration = songDuration; } public Album getAlbum() { return album; } public void setAlbum(Album album) { this.album = album; } // 如果需要获取专辑ID,可以通过album.getAlbumId()获取,无需单独存储 }
2. 修正Album类的@OneToMany关联
在Album的songs属性上添加mappedBy,指定这个关联由Song类的album属性维护,避免JPA生成额外的外键列:
@Entity @Table(name = "albums", schema = "dbo") public class Album { @Id @GeneratedValue @Column(name = "album_id") private Integer albumId; @Column(name = "album_name") private String albumName; @Column(name = "released_by") private String releasedBy; @Column(name = "total_duration") private Integer totalDuration; // 修正关联配置 @OneToMany(mappedBy = "album") // 指定关联由Song的album属性维护 private List<Song> songs; // getter和setter方法 public Integer getAlbumId() { return albumId; } public void setAlbumId(Integer albumId) { this.albumId = albumId; } public String getAlbumName() { return albumName; } public void setAlbumName(String albumName) { this.albumName = albumName; } public String getReleasedBy() { return releasedBy; } public void setReleasedBy(String releasedBy) { this.releasedBy = releasedBy; } public Integer getTotalDuration() { return totalDuration; } public void setTotalDuration(Integer totalDuration) { this.totalDuration = totalDuration; } public List<Song> getSongs() { return songs; } public void setSongs(List<Song> songs) { this.songs = songs; } }
3. 调整服务类的逻辑(可选优化)
因为现在Song已经直接关联了Album,你可以直接从song.getAlbum()获取专辑信息,不需要再通过albums.findById()查询,提升性能:
@Service public class Services { // 可以移除AlbumRepository的注入,除非有其他用途 @Autowired private SongRepository songs; public SongViewModel translateToViewModel(Song song) { SongViewModel model = new SongViewModel(); model.setSongId(song.getSongId()); model.setSongName(song.getSongName()); model.setSongDuration(song.getSongDuration()); // 直接从关联的Album对象获取名称 model.setSongAlbumName(song.getAlbum().getAlbumName()); model.setSongAlbumId(song.getAlbum().getAlbumId()); return model; } // ...其他方法 }
验证修改后的SQL
修复后,JPA生成的查询SQL会变成:
select song0_.song_id as song_id1_1_, song0_.album_id as album_id2_1_, song0_.song_duration as song_dur3_1_, song0_.song_name as song_nam4_1_ from dbo.songs song0_
不再包含不存在的album_album_id列,错误也就解决了。
内容的提问来源于stack exchange,提问作者justanotherguy
相关产品推荐
相关产品推荐

