问题描述
我正在努力解决这个奇怪的错误:CrudRepository
的findById()
方法返回Optional.empty
,除非在使用mysql之前已调用findAll()
.
I'm struggling with this strange error: the findById()
method of a CrudRepository
returns Optional.empty
, unless findAll()
is called before when using mysql.
例如
用户
@Entity
public class User {
@Id
@GeneratedValue
private UUID id;
public UUID getId() {
return id;
}
}
UserRepository
UserRepository
public interface UserRepository extends CrudRepository<User, UUID> { }
UserService
UserService
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public UUID create() {
final User user = new User();
userRepository.save(user);
return user.getId();
}
@Transactional
public User find(@PathVariable UUID userId) {
// userRepository.findAll(); TODO without this functin call, Optinoal.empty is returned by the repo
return userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException(String.format("missing user:%s", userId)));
}
}
UserApp
@SpringBootApplication
public class UserApp {
private static final Logger LOG = LoggerFactory.getLogger(UserApp.class);
@Autowired
private UserService userService;
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
final UUID userId = userService.create();
final User user = userService.find(userId);
LOG.info("found user: {}", user.getId());
}
public static void main(String[] args) {
SpringApplication.run(UserApp.class, args);
}
}
application.properties
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/db_test
spring.datasource.username=springuser
spring.datasource.password=ThePassword
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.database=mysql
为什么findAll()
方法调用会更改findById()
的结果?
Why does the findAll()
method call change the result of findById()
?
使用findAll
休眠日志:
Hibernate: drop table if exists user
Hibernate: create table user (id binary(255) not null, primary key (id)) engine=MyISAM
Hibernate: insert into user (id) values (?)
Hibernate: select user0_.id as id1_0_ from user user0_
没有:
Hibernate: drop table if exists user
Hibernate: create table user (id binary(255) not null, primary key (id)) engine=MyISAM
Hibernate: insert into user (id) values (?)
Hibernate: select user0_.id as id1_0_0_ from user user0_ where user0_.id=?
推荐答案
我遇到了同样的问题.根本原因是不可空的@ManyToOne关系与表中保留的数据之间的不匹配.我有这个:
I was facing the same issue. The root cause was the mismatch between non-nullable @ManyToOne relation and the data persisted in table.I had this:
@ManyToOne(optional = false)
@JoinColumn(name="batch_id")
private Batch batch;
表示batch_id在任何行中都不能为null.但是,我的行的batch_id外键具有空值.删除optional = false(这是预期的业务规则)后,findById开始按预期工作.
which means batch_id can't be null in any row. However, my rows had null value for batch_id foreign key. After removing optional = false (which is the expected business rule), findById started working as expected.
从该线程获得指示:
这篇关于春季数据JPA-mysql-findById()为空,除非之前调用过findAll()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!