我在使用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)返回null结果。 hibernate生成的sql和消息是以下输出:
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',因此它返回null结果,但为什么会发生这种情况呢?我的代码出了什么问题?我检查了春季jpa参考,但我没有找到答案。请给我一些建议并提前感谢!
答案 0 :(得分:1)
首先,你正在寻找错误的地方。你有一个JPA映射问题,你的JPA实现是Hibernate。因此,您应该在JPA / Hibernate文档中查找问题,而不是在Spring文档中。
您告诉JPA / Hibernate,TimebankEntity与UserEntity之间存在关联:
@ManyToOne
@JoinColumn(name = "username")
private UserEntity user;
这意味着表username
中有一列tb_timebank
,用于引用tb_user
表的一行。但是你不能在任何地方说出这一列引用的tb_user
表的哪一列。
唯一引用另一个表的行的最自然的方法是什么?当然是主键。所以,当然,如果您没有指定任何内容,那就是JPA将使用的内容。怎么改变?
让我们阅读API documentation of JoinColumn:
referencedColumnName
public abstract java.lang.String referencedColumnName
(可选)此外键列引用的列的名称。
[...]
默认值(仅在使用单个连接列时适用):与引用表的主键列相同的名称。
因此,默认情况下,引用的列名称是引用表的主键列的名称,即tb_user.id
。
要引用另一列,您需要为此属性指定一个值:
@JoinColumn(name = "username", referencedColumnName = "username")
也就是说,您最好使用默认值:如果两个用户具有相同的名称,并且不会强制您更新{{},那么效率会更高,不会导致问题。 1}}当用户更改其名称时