Хранилище CRUD не соблюдает УНИКАЛЬНОЕ ограничение - PullRequest
1 голос
/ 11 мая 2019

У меня есть следующий объект 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 Ответ

2 голосов
/ 11 мая 2019

Это происходит потому, что не выдан оператор insert.

Hibernate не flush сеанс , если у него нет веских причин для этого .

  1. @DataJpaTest - @Transactional.Это означает, что транзакция, выполняемая в методе @Test, откатывается после его возврата.
  2. UserEntity отображение также стимулирует спящий режим для задержки insert (попробуйте использовать свойство @GeneratedValue(strategy = IDENTITY) для idдля принудительной выдачи insert s)

Не вдаваясь в подробности, при запуске теста происходит следующее:

  1. Тестовая инфраструктура Spring * Транзакция 1030 * s
  2. @Test метод запускается
  3. save(testUserEntity) - Hibernate понимает, что нет никаких причин обращаться к базе данных, и задерживает insert
  4. shouldThrow<SQLException> { save(newUserEntity) } - аналогично предыдущему
  5. @Test метод возвращает
  6. Транзакция откатывается.Hibernate выполняет insert s, потому что нет никаких причин.

Как это исправить?

Самый простой способ сделать это - использовать 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

*1065**1066*

не существует метода * Я думаю, чтоВы расширили CrudRepository ... Вместо этого вы можете захотеть расширить JpaRepository.

См .: В чем разница между интерфейсами CrudRepository и JpaRepository в Spring Data JPA?


Примечание по исключению

Вы ожидаете бросить SQLException.

Но учтите, что вместо этого будет выброшено DataIntegrityViolationException.

См .: Иерархия последовательных исключений

...