[英]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将使用此内容。 如何改变呢?
让我们阅读JoinColumn的API文档 :
referencedColumnName
公共抽象java.lang.String referencedColumnName
(可选)此外键列引用的列的名称。
[...]
默认值(仅在使用单个连接列时适用):与引用表的主键列相同的名称。
因此,默认情况下,引用的列名称是referencedtable的主键的列的名称,即tb_user.id
。
要引用另一列,您需要为此属性指定一个值:
@JoinColumn(name = "username", referencedColumnName = "username")
就是说,您最好使用默认值:这将更有效,如果两个用户具有相同的名称,则不会引起问题,并且不会在用户更改其名称时强制您更新tb_timebank
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.