繁体   English   中英

Spring JPA findByDomainClass生成错误的where子句

[英]Spring JPA findByDomainClass generates wrong where clause

使用Spring JPA时遇到问题。 我用谷歌搜索了半天,但没有结果。 让我向您展示我的代码。 我编写了一个实体,该实体引用数据库中带有外键的另一个域类,但是该实体的连接列不是主键“ id”。 这两个实体如下:

@Entity
@Table(name = "tb_user")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String username;
    ... getters and setters ...
}

@Entity
@Table(name = "tb_timebank")
public class TimebankEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "username")
    private UserEntity user;
    ... getters and setters ...
}

我使用spring JPA CrudRepository进行自定义查询:

@Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> {
    public UserEntity findByUsername(String username);
}

@Repository
public interface TimebankRepository extends CrudRepository<TimebankEntity, Long> {
    public TimebankEntity findByUser(UserEntity user);
}

那很简单。 但是,当我在服务中执行业务逻辑时,出现了问题。

@Service
public class TimebankService {
    @Autowired
    TimebankRepository timebankRepository;

    @Autowired
    UserRepository userRepository;
    public TimebankDto getTimebank(String username) {
        UserEntity userEntity = userRepository.findByUsername(username);
        TimebankEntity timebankEntity = timebankRepository
                .findByUser(userEntity);
        return new TimebankDto(timebankEntity.getUser().getUsername(),
                timebankEntity.getLeaveType().getCode(),
                timebankEntity.getTotalHours(),
                timebankEntity.getAvailableHours());
    }
}

我使用用户名“ Tom”运行上面的代码,我可以获取数据库中存在的正确的userEntity。 但是findByUser(userEntity)返回空结果。 hibernate生成的sql和message是以下输出:

Hibernate: select userentity0_.id as id1_2_, userentity0_.introduction as introduc2_2_, userentity0_.password as password3_2_, userentity0_.username as username4_2_ from tb_user userentity0_ where userentity0_.username=?
Hibernate: select timebanken0_.id as id1_1_, timebanken0_.available_hours as availabl2_1_, timebanken0_.leave_type as leave_ty4_1_, timebanken0_.total_hours as total_ho3_1_, timebanken0_.username as username5_1_ from tb_timebank timebanken0_ left outer join tb_user userentity1_ on timebanken0_.username=userentity1_.id where userentity1_.id=?
o.h.engine.jdbc.spi.SqlExceptionHelper:SQL Warning Code: 1292, SQLState: 22007
o.h.engine.jdbc.spi.SqlExceptionHelper:Truncated incorrect DOUBLE value: 'Tom'

似乎“ Tom”已分配给字段“ id”,因此它返回空结果,但是为什么会发生这种情况? 我的代码有什么问题? 我检查了spring jpa参考,但没有找到答案。 请给我一些建议,并感谢提前!

首先,您正在寻找错误的位置。 您在这里有一个JPA映射问题,并且您的JPA实现是Hibernate。 因此,您应该在JPA / Hibernate文档中而不是在Spring文档中查找问题。

您已经告诉JPA / Hibernate,TimebankEntity和UserEntity之间存在关联:

@ManyToOne
@JoinColumn(name = "username")
private UserEntity user;

因此,这意味着在表tb_timebank中存在一列username ,该username用于引用tb_user表的一行。 但是您在任何地方都不会说此列引用tb_user表的tb_user列。

唯一引用另一张表的最自然的方法是什么? 当然是主键。 因此,当然,如果您不指定任何内容,那么JPA将使用此内容。 如何改变呢?

让我们阅读JoinColumnAPI文档

referencedColumnName

公共抽象java.lang.String referencedColumnName

(可选)此外键列引用的列的名称。

[...]

默认值(仅在使用单个连接列时适用):与引用表的主键列相同的名称。

因此,默认情况下,引用的列名称是referencedtable的主键的列的名称,即tb_user.id

要引用另一列,您需要为此属性指定一个值:

@JoinColumn(name = "username", referencedColumnName = "username")

就是说,您最好使用默认值:这将更有效,如果两个用户具有相同的名称,则不会引起问题,并且不会在用户更改其名称时强制您更新tb_timebank

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM