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

CRUD存储库不尊重唯一约束

令狐烨烨
2023-03-14

我有以下JPA实体

@Entity
class UserEntity {

    companion object {
        fun fromParameters(uuid: String, email: String, password: String, firstName: String, lastName: String) =
            UserEntity().apply {
                this.uuid = uuid
                this.email = email
                this.password = password
                this.firstName = firstName
                this.lastName = lastName
            }
    }

    @Id
    lateinit var uuid: String

    @Column(nullable = false, unique = true)
    lateinit var email: String

    @Column(nullable = false)
    lateinit var password: String

    @Column(nullable = false)
    lateinit var firstName: String

    @Column(nullable = false)
    lateinit var lastName: String
}

这是我检查唯一约束的测试,插入具有相同电子邮件的另一个用户。

@RunWith(SpringRunner::class)
@DataJpaTest
@AutoConfigureTestEntityManager
class TestUserCrudRepository {

    @Autowired
    private lateinit var userCrudRepository: UserCrudRepository

    private val testUserEntity = UserEntity.fromParameters(
        UUID.randomUUID().toString(),
        "test@test.com",
        "password".toHash(),
        "Caetano",
        "Veloso"
    )

    @Test
    fun `when email already exists it should throw error`() {
        with (userCrudRepository) {
            save(testUserEntity)
            val newUserEntity = with (testUserEntity) { UserEntity.fromParameters(UUID.randomUUID().toString(), email, password, firstName, lastName) }
            shouldThrow<SQLException> { save(newUserEntity) }
        }
    }
}
Expected exception java.sql.SQLException but no exception was thrown
Hibernate: drop table user_entity if exists
Hibernate: create table user_entity (uuid varchar(255) not null, email varchar(255) not null, first_name varchar(255) not null, last_name varchar(255) not null, password varchar(255) not null, primary key (uuid))
Hibernate: alter table user_entity add constraint UK_4xad1enskw4j1t2866f7sodrx unique (email)

共有1个答案

齐夕
2023-03-14

发生这种情况的原因是没有发出insert语句。

Hibernate不会刷新会话,除非它有充分的理由这样做。

  1. @datajpatest@transactional。这意味着在@test方法中执行的事务将在该方法返回后回滚。
  2. userentity映射还鼓励hibernate延迟insert(尝试在id属性上使用@generatedvalue(strategy=IDENTITY)强制发出insert)

在运行测试时,不需要深入研究太多细节,会发生以下情况:

  1. Spring的测试基础结构begin的事务
  2. @test方法运行
  3. save(testUserEntity)-Hibernate意识到没有理由命中数据库并延迟insert
  4. shouldthrow {save(newUserEntity)} -与上一页相同
  5. @test方法返回
  6. 事务回滚。Hibernate确实执行inserts,因为没有理由执行。

最简单的方法是使用jparepository#flush:

with (userCrudRepository) {
    save(testUserEntity)
    val newUserEntity = with (testUserEntity) { UserEntity.fromParameters(UUID.randomUUID().toString(), email, password, firstName, lastName) }
    save(newUserEntity)
    assertThrows<DataIntegrityViolationException> {
        flush()
    }
}

我猜您已经扩展了crudrepository...您可能希望扩展jparepository

请参见:Spring Data JPA中的CrudRepository和JpaRepository接口之间有什么区别?

例外情况说明

您希望抛出SQLException

参见:一致的异常层次结构

 类似资料:
  • 我正在做一个项目,其中我有一个节点之间的距离矩阵,我导入到cplex。我这样做: 它导入所有内容,但当我添加限制时,距离矩阵不受尊重,变量显示没有连接的节点之间的连接。另外,最后的限制改变了q的值,为什么会发生这种情况?我怎样才能解决这个问题? 提前谢谢。 目标函数和限制条件如下:

  • 我在玩spring数据存储库,有一个关于编写CRUD测试的问题。我针对Hibernate DAO和EJB3实体bean编写了许多CRUD测试,在这些测试中,我创建和实体,将其刷新到数据库中,清除实体管理器,并按ID读回它。实体管理器被清除,因此第一级缓存不会在读取时被击中。 使用spring数据存储库,我找不到一种方法来清除测试使用的底层实体管理器,这样我的读取就不会返回到实际的数据库,使我的测试

  • 这是我的限制: 该查询证明约束实际上不起作用: 下面是输出: 为什么唯一性没有被强制执行?

  • 这根本不是关于Spring靴的。 我的英语可以更好。 使用下面的Spring Data配置,我正在尝试执行DML请求。 恰好是< code>CrudRepository#save方法。 然而,执行Spring的CrudRepository#保存方法,我接下来要做的是: 只有选择由功能记录。 没有执行任何“插入”或“更新”语句来hibernate.show_sql日志记录。 数据库根本没有变化。 =

  • 我正在尝试使用jooq使用batchStore插入记录。我需要知道如何在唯一约束上更新记录,目前它抛出一个异常,该记录已经存在 下面是代码 目前,它可以很好地插入记录,但当根据唯一约束发现重复记录时,它应该更新记录

  • 我有一个数据已经保存在我的数据库基于我的存储库和服务。我想保存另一个数据与邮递员只改变播放器id。但它不是创建一个新的实体数据。它更新现有的实体数据。我的问题是如何更新一个数据由我的服务当它找到一个现有的id。但当它找到一个新的id将保存一个新的数据到数据库。 这是我的回购: 这是我的服务: