Я просто тестировал свой класс UserRepo, пока не получил ошибку, указанную в заголовке. Некоторая информация: Моим первичным ключом для таблицы пользователей является имя пользователя (это строка, предоставляемая пользователями, которые входят в приложение).
У меня есть производственная база данных с postgresql, где все это прекрасно работает. Для моих тестовых классов я использую h2 db.
У меня есть класс пользователя:
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "users")
public class User{
@Id
@NotBlank(message = "Username is required")
private String username;
@NotBlank(message = "Email is required")
private String email;
@NotBlank(message = "Password is required")
private String password;
@ManyToMany(cascade = CascadeType.ALL)
private Collection<Role> roles = new ArrayList<>();
private Instant created;
private boolean enabled;
}
У меня нет идентификатора пользователя, так как я хотел, чтобы имена пользователей были уникальными, поэтому я использовал его в качестве своего идентификатора. Мой тестовый класс:
@DataJpaTest
class UserRepoTest {
@Autowired
private UserRepo userRepo;
@PersistenceContext
private EntityManager entityManager;
private static User userWithNameAdministrator;
@BeforeAll
static void beforeAll() {
userWithNameAdministrator = UserBuilder.user("administrator", "[email protected]", "administrator").buildUser();
}
@Test
void itShouldfindByUsername() {
// given
User expectedUser = userWithNameAdministrator;
userRepo.save(expectedUser);
// when
String username = expectedUser.getUsername();
User actualUser = userRepo.findByUsername(username);
// then
assertThat(actualUser).usingRecursiveComparison()
.isEqualTo(expectedUser);
}
А теперь мой метод построителя для пользователя:
public static UserBuilder user(String username, String email, String role) {
ArrayList<Role> roles = new ArrayList<>();
roles.add(new Role(null, role));
return user()
.withUsername(username)
.withEmail(email)
.withEnabled(true)
.withPassword("t")
.withCreated(Instant.now())
.withRoles(roles);
}
Это еще один класс в пакете Builder.
Наконец мой RepoClass:
@Repository
public interface UserRepo extends JpaRepository<User, Long> {
User findByUsername(String username);
}
После поиска в Интернете я обнаружил, что Hibernate ищет последовательность, но, поскольку у меня нет аннотации @GeneratedValue, он будет использовать по умолчанию. Есть несколько вопросов по этому поводу, но я, похоже, не нашел ни одного с пользовательским идентификатором (строка) вместо длинного идентификатора.
Пожалуйста, создайте последовательность, используя SQL.
создать последовательность hibernate_sequence;
@DJFreeman Пожалуйста, не указывайте @GeneratedValue, оно вычисляется автоматически и не поможет. Если вы используете h2 только в памяти, вы можете изменить URL-адрес следующим образом: jdbc:h2:mem:test;INIT=create sequence hibernate_sequence;
. Убедитесь, что ваши таблицы также созданы. Ссылка: h2database.com/html/features.html#execute_sql_on_connection
У вас есть какой-нибудь ресурс о том, как это сделать для h2? Или мне просто нужно указать @GeneratedValue (IdentityType = Sequence)?