当前位置: 首页 > 知识库问答 >
问题:

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

万俟鸿波
2023-03-14

我试图学习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个答案

胡天佑
2023-03-14

这不是您的保存(…) 是可选的,但是用户DAO。findById(admin.getName())。根据文档,crudeposiotry提供了一个返回类型为可选的findById()

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

如果您不希望可选作为返回类型,则需要提供自己的方法来执行此操作。例如:

public interface PeronRepository extends CrudRepository<Person, String> {
    Person findById(String personId);
}
洪国兴
2023-03-14

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

然后,Spring data jpa使用可选来避免NullPointException,实际上它很有用。如果您想使用Spring-data-jpa提供的接口,那么您也必须使用可选。您可以在此处查看有关可选:link 1、link 2的更多信息

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

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

这样,您就不需要处理可选或考虑NullPointException。

或:

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

这样,如果您找不到目标实体,那么它将为空。所以不要忘记检查实体是否为空。

希望能有所帮助~~~

 类似资料:
  • 我正在尝试开发一个小型电子商务项目。我有一个篮子和篮子项目实体。我只是想当我为客户保存购物篮时,我想把购物篮项目保存在数据库中。我认为我不应该为篮子项目创建存储库。我应该能够保存篮子项目,同时使用篮子存储库保存篮子。 在这里,我试图通过篮子服务获得一个篮子项目,并将其设置为篮子实体并保存它。 我有什么问题?我有个例外。

  • 我在SQL服务器数据库中有表用户,有近30列。我还为相应的数据库表创建了一个JPA实体。JPA实体如下所示: 现在我正在尝试创建一个本机查询,它只会从用户表中获取id和name。Repository类看起来像这样。 现在,当它被执行时,它会抛出一个异常,如下所示: 当我将地址列添加到我的查询时,这个异常会消失,但它会出现在另一个字段中。 所以,现在我想修改JPA实体,使这个字段成为可选的。我试过使

  • 我有两个具有@ManyToOne关系的实体类,如下所示。 我是Spring Data JPA的新手,所以这可能是一个非常基本的错误。

  • 无论如何,如果用户名已经被使用,存储库只需进行更新,因为指定的标识符不是空的。这不是我想要的行为,我需要它抛出类似重复条目异常的东西。有什么办法可以预防吗?我必须自己做吗?例如:

  • 我有一个具有2级层次结构的TreeView控件。如果选择了第二级的项目,并且用户单击了另一个项目,我需要询问他是否确定要移动到另一个项目。如果他的答案是“否”,我需要阻止选择另一个TreeViewItem。 我试着这样做: 以一种有效的方式。但是,问题是我得到了两次OnMouseDown事件:第一级项目和第二级项目。例如,对于这棵树:俄罗斯-莫斯科-皮特美国-纽约-波士顿如果我单击波士顿,我将获得

  • 我尝试读取ExcelFiles并将数据保存在postgres数据库中。在某些文件中,我会得到以下错误消息: null 在大多数已爬网的数据中,什么都没有发生。当我尝试保存semster对象时会出现错误。Excel文件的结构如下:标题、模块号、语言、学期号