保存到CRUDRepository时,如何防止Spring JPA实体成为可选的?

时间:2018-11-21 07:05:42

标签: java spring spring-data-jpa

我试图学习Spring Framework并遇到将实体保存到CRUD存储库的问题。我很少有带有自动数字ID生成的实体,并且它们工作得很好,但是后来我尝试创建一个以String作为主键的类,如下所示:

@Entity
@Table(name = "USERS")
@Builder
public class User {
    @Id
    @Column(name = "USER_NAME", nullable = false)
    @Getter @Setter
    private String name;

    @Column(name = "USER_PASS", nullable = false)
    @Getter @Setter
    private String pass;
}

首先,我收到关于此类没有默认构造函数的异常的信息:

org.springframework.orm.jpa.JpaSystemException: No default constructor for entity:  : com.company.Model.User; nested exception is org.hibernate.InstantiationException: No default constructor for entity:  : com.company.Model.User

已经很奇怪了,但是我仍然决定将@Builder注解更改为2个构造函数,一个带有两个参数,另一个不带参数。我尝试通过典型测试将实体实例保存到CRUD存储库userDAO(仅是扩展CRUDRepository的接口):

User admin = new User("admin", "6aDcZ72k");

...

@Test
public void saveUserAndFindById() {
    admin = userDAO.save(admin);
    assertThat(userDAO.findById(admin.getName())).isEqualTo(admin);
}

结果是断言失败,因为保存的实体具有“可选”类型:

org.junit.ComparisonFailure: 
Expected :com.company.Model.User@2c06b113
Actual   :Optional[com.company.Model.User@2c06b113]

我知道我做错了什么,但无法解决。也许有一种方法可以防止将其设置为可选?该类上必须有很少的其他实体具有该引用,但由于上述问题,这些引用显然不起作用。

2 个答案:

答案 0 :(得分:1)

返回save(...)的不是您的Optional,而是userDAO.findById(admin.getName()。根据文档,CrudReposiotry提供了一个findById(),其返回类型为Optional<T>

public interface CrudRepository<T, ID extends Serializable>
  extends Repository<T, ID> {
    Optional<T> findById(ID primaryKey);
}

如果您不希望将Optional作为返回类型,则需要提供自己的方法。例如:

public interface PeronRepository extends CrudRepository<Person, String> {
    Person findById(String personId);
}

答案 1 :(得分:0)

首先, jpa要求实体具有No Arguments构造函数,因为它将首先创建一个实例,然后填充它。最简单的方法是在实体上添加lombok提供的@NoArgumentsConstructor类。

然后,spring数据jpa使用Optional来避免NullPointException,实际上它实际上是有用的。如果要使用Spring-data-jpa提供的接口,那么也必须使用Optional。您可以在此处查看有关可选的更多信息:link1link2

顺便说一句,我通常这样使用它:

ExampleEntity example=exampleRepository.findById(id).orElseThrow(()->new ExampleNotFoundException());

通过这种方式,您无需处理Optional或考虑NullPointException。

或:

ExampleEntity example=exampleRepository.findById(id).orElse(null);

这样,如果找不到目标实体,那么它将为空。因此,请不要忘记检查该实体是否为空。

希望它可以帮助~~~