nag*_*hun 9 mysql spring spring-data spring-data-jpa
我正在为这个奇怪的错误而苦苦挣扎: a 的findById()方法CrudRepository返回Optional.empty,除非findAll()在使用 mysql 之前被调用。
例如
用户
@Entity
public class User {
@Id
@GeneratedValue
private UUID id;
public UUID getId() {
return id;
}
}
Run Code Online (Sandbox Code Playgroud)
用户库
public interface UserRepository extends CrudRepository<User, UUID> { }
Run Code Online (Sandbox Code Playgroud)
用户服务
@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)));
}
}
Run Code Online (Sandbox Code Playgroud)
用户应用程序
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序属性
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
Run Code Online (Sandbox Code Playgroud)
为什么findAll()方法调用会改变 的结果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_
Run Code Online (Sandbox Code Playgroud)
没有:
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=?
Run Code Online (Sandbox Code Playgroud)
小智 6
我面临着同样的问题。根本原因是不可空的 @ManyToOne 关系与表中持久化的数据之间不匹配。我有这个:
@ManyToOne(optional = false)
@JoinColumn(name="batch_id")
private Batch batch;
Run Code Online (Sandbox Code Playgroud)
这意味着任何行中的batch_id 都不能为空。但是,我的行的batch_id 外键具有空值。删除Optional = false(这是预期的业务规则)后,findById开始按预期工作。
从这个线程得到指示:我厌倦了用 JpaRepository 做一些事情但无法使用 findById 找到行,
小智 5
正如之前(但更笼统地)在一些测试之后已经写过的那样,我的结论是当@ManyToOne 关系中的必填字段和数据库数据存在差异时会出现问题。例如,假设有一个没有必填字段约束的表,但同时你的 Hibernate 模型类带有 @ManyToOne(optional = false) 约束。并想象填充表(例如使用 SQL 脚本),将被指示的字段保留为null。当您尝试执行findById()、deleteById或任何暗示通过 Id 获取的操作时,您将遇到这种(可怕的)副作用。
尝试使用下面的代码;
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Type(type="uuid-char")
private UUID id;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1384 次 |
| 最近记录: |