我试图学习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]
我知道我做错了什么,但无法解决。也许有一种方法可以防止将其设置为可选?该类上必须有很少的其他实体具有该引用,但由于上述问题,这些引用显然不起作用。
答案 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。您可以在此处查看有关可选的更多信息:link1,link2
顺便说一句,我通常这样使用它:
ExampleEntity example=exampleRepository.findById(id).orElseThrow(()->new ExampleNotFoundException());
通过这种方式,您无需处理Optional或考虑NullPointException。
或:
ExampleEntity example=exampleRepository.findById(id).orElse(null);
这样,如果找不到目标实体,那么它将为空。因此,请不要忘记检查该实体是否为空。
希望它可以帮助~~~