spring data JPA - mysql - findById()empty除非findAll()之前调用

pb3s4cty  于 2023-05-05  发布在  Spring
关注(0)|答案(4)|浏览(247)

我在纠结这个奇怪的错误:CrudRepositoryfindById()方法返回Optional.empty,除非之前在使用mysql时调用了findAll()
例如
使用者

@Entity
public class User {

    @Id
    @GeneratedValue
    private UUID id;

    public UUID getId() {
        return id;
    }

}

UserRepository

public interface UserRepository extends CrudRepository<User, UUID> { }

用户服务

@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

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()的结果?
编辑:使用findAll的Hibernate日志:

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=?
unguejic

unguejic1#

正如之前已经写过的(但更一般地),经过一些测试,我的结论是,当@ManyToOne关系中的必填字段和数据库数据存在差异时,就会出现问题。例如,假设有一个没有强制字段约束的表,但同时你的Hibernate模型类有一个@ManyToOne(optional = false)约束。想象一下填充表(比如使用SQL脚本),留下被起诉的字段为 null。当你尝试执行 findById()deleteById或任何隐含get by Id的操作时,你会遇到这种(可怕的)副作用。

wydwbb8l

wydwbb8l2#

我也面临着同样的问题。根本原因是不可空的@ManyToOne关系与表中持久化的数据之间不匹配。我有这个:

@ManyToOne(optional = false)
  @JoinColumn(name="batch_id")
  private Batch batch;

这意味着batch_id在任何行中都不能为null。但是,我的行的batch_id外键为空值。删除optional = false(这是预期的业务规则)后,findById开始按预期工作。
从这个线程得到的指示:I tired to do something with JpaRepository But Can not find row with findById ,

jobtbby3

jobtbby33#

尝试使用下面的代码;

@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Type(type="uuid-char")
private UUID id;
nwlqm0z1

nwlqm0z14#

与其他答案中提到的不正确的'optional'类似,我也遇到过这样的情况:在数据库中,一个属性上的@javax.validation.constraints.NotNull注解实际上是null

相关问题