【问题标题】:JPA can not set Long field to LongJPA 无法将 Long 字段设置为 Long
【发布时间】:2017-01-25 15:45:46
【问题描述】:

我想我在某个地方搞错了......
假设 1 个玩家有 1 个统计表 (oneToOne)

类玩家:

@Component
@Entity
@Table(name = "player")
public class Player {

    @Id
    @GeneratedValue
    @JsonView(View.Summary.class)
    @Column(name = "id")
    private Long id;

    @Column(name = "uid", unique = true, nullable = false)
    @JsonView(View.Summary.class)
    private Long uid;

    @OneToOne(mappedBy = "player", cascade = CascadeType.ALL)
    @JsonView(View.Summary.class)
    private Stats stats;
    ....

班级统计:

@Component
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "stats")
public class Stats implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @JsonView(View.Summary.class)
    @Column(name = "id")
    private Long id;

    @OneToOne
    @JoinColumn(name = "player_uid", referencedColumnName = "uid", nullable = false)
    @JsonView(View.Summary.class)
    private Player player;
    ....

类 PlayerDAO:

public interface JPAPlayerDAO extends JpaRepository<Player, Long> {
    Player findByUid(Long uid);
    Player findByName(String name);
}

如果我这样做,那很好:

Player p = new Player();
p.setUid(123L);
p.setName("Mike");
updater.saveOrUpdatePlayer(p);
p = playerDAO.findOne()

如果我尝试按名称或 uid 查找它,我会收到错误:

Player p = new Player();
p.setUid(123L);
p.setName("Mike");
updater.saveOrUpdatePlayer(p);
p = playerDAO.findByName("Mike")
or
p = playerDAO.findByUid(123L)
....
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field...
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field ...entities.Player.uid to java.lang.Long

我认为我的 oneToOne 参考可能有问题。

【问题讨论】:

  • 如果我删除一个参考。从 stats 到 uid @JoinColumn (name = "player_uid", referencedColumnName = "uid"),一切正常。但我需要它。

标签: java hibernate spring-boot spring-data-jpa


【解决方案1】:

如果我删除一个参考。从 stats 到 uid @JoinColumn (name = "player_uid", referencedColumnName = "uid"),一切正常。

如果是这种情况,问题可能出在您已经提到的关联上。 根据 JPA 规范,对非主键映射的支持是可选的,这意味着它不能被支持:

11.1.25 JoinColumn 注释

...

如果缺少 referencedColumnName 元素,则假定外键引用被引用表的主键。

支持不是被引用表的主键列的被引用列是可选的。使用此类映射的应用程序将不可移植。

所以你应该把注解改成:

@JoinColumn(name = "player_uid", referencedColumnName = "id")

或删除referencedColumnName,因为提供程序将使用默认主键(在本例中为id)。

【讨论】:

  • 如果是这样,我认为我会从 Player 中删除 id,然后将使用 uid 作为@id 并将 Stats 绑定到此 uid。谢谢。
  • 是的,重要的是您将该字段设为Player 实体的主键。
【解决方案2】:

我认为您需要在这里实现 PlayerDAO。你可以试试这样的

@Repository    
public interface JPAPlayerDAOImpl extends JPAPlayerDAO, JpaRepository<Player, Long> {

    @Override
    @Query("SELECT player FROM Player player WHERE player.uid =:uid")
    Player findByUid(@Param("uid") Long uid);

    @Override
    @Query("SELECT player FROM Player player WHERE player.name =:name")
    Player findByName(@Param("name") String name);
}

PlayerDAO 将如下所示:

public interface JPAPlayerDAO {
   Player findByUid(Long uid);
   Player findByName(String name);
} 

【讨论】:

  • JPAPlayerDAO 使用 Spring Data 存储库接口,因此会自动创建实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 2020-02-26
  • 2020-12-02
相关资源
最近更新 更多