org.springframework.dao.InvalidDataAccessResourceUsageException:执行独立工作时出错; SQL

问题描述 投票:0回答:2

我想测试我的 UserRepository,但我不断收到此错误 ```org.springframework.dao.InvalidDataAccessResourceUsageException:执行隔离工作时出错; SQL [n/a]```` 我不知道我哪里出错了。我想使用 H2 作为测试的数据库,因此为什么 h2 依赖范围是 test。我想也许原因是这样的

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "_USER_SEQ" not found (this database is empty); SQL statement:
select next_val as id_val from _user_seq for update [42104-214]

但是我不知道,请帮忙。

用户存储库测试:

package com.david.caterest.repository;

import com.david.caterest.entity.User;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldFindStudentWhenGivenExistentEmail() {
        // given
        String email = "[email protected]";
        User user = new User();
        user.setEmail(email);
//        when(userRepository.findByEmail(email)).thenReturn(Optional.of(user));
        userRepository.save(user);
        // when
        Optional<User> result = userRepository.findByEmail(email);

        // then
        assertThat(result).isPresent();
        assertThat(result.get()).isEqualTo(user);
    }

    @Disabled
    @Test
    void shouldNotFindStudentWhenGivenNonexistentEmail() {
        
    }
    
}

用户存储库:

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByDisplayNameAndPassword(String username, String password);
    Optional<User> findByDisplayName(String username);
    Optional<User> findByEmail(String email);
    Boolean existsByEmail(String email);

}

用户:

package com.david.caterest.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Setter
@Getter
@RequiredArgsConstructor
@Entity
@Table(name = "_user")
public class User implements UserDetails {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Lob
    @Column(length = 31_457_280) // 30MB
    private Byte[] profilePicture;

//    @NotBlank
    private String displayName;

//    @NotBlank
    private String firstName;

//    @NotBlank
    private String lastName;

//    @NotBlank
    @Column(unique = true)
    private String email;

//    @NotBlank
    private String password;

    private String biography;
    private LocalDate dateOfBirth;
    private String telephoneNumber;
    private String city;
    private String country;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private List<Picture> pictures = new ArrayList<>();

    @Enumerated(EnumType.STRING)
    private Role role;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(new SimpleGrantedAuthority(role.name()));
    }

    public String getUsername() {
        return email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

application.properties(测试):

spring.datasource.url=jdbc:h2://mem:db;DB_CLOSE_DELAY=-1
#spring.datasource.url=jdbc:h2:mem:test_db
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.format_sql=true

spring.servlet.multipart.max-file-size=10MB
server.error.include-message=always

堆栈跟踪:

org.springframework.dao.InvalidDataAccessResourceUsageException: error performing isolated work; SQL [n/a]

    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:256)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:232)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:163)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
    at jdk.proxy2/jdk.proxy2.$Proxy117.save(Unknown Source)
    at com.david.caterest.repository.UserRepositoryTest.shouldFindStudentWhenGivenExistentEmail(UserRepositoryTest.java:26)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
...
...
Caused by: org.hibernate.exception.SQLGrammarException: error performing isolated work
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:64)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:79)
    at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:135)
    at org.hibernate.id.enhanced.PooledOptimizer.generate(PooledOptimizer.java:73)
    at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:536)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:114)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:184)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:129)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:53)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:737)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:721)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
    at jdk.proxy2/jdk.proxy2.$Proxy108.persist(Unknown Source)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:613)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:77)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    ... 76 more
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "_USER_SEQ" not found (this database is empty); SQL statement:
select next_val as id_val from _user_seq for update [42104-214]
java spring junit
2个回答
2
投票

此问题似乎与 Hibernate 和 H2 数据库的错误配置有关。当您使用 spring.jpa.hibernate.ddl-auto=create-drop 属性时,Hibernate 将基于 @Entity 类创建必要的表。但是,您的用户序列(_USER_SEQ)的创建似乎失败了。

主要问题是表和列的命名。在 SQL 中,以下划线 _ 开头的标识符被视为系统标识符,应避免使用。当 Hibernate 尝试使用系统标识符创建表时,它可能会失败或导致意外行为。

尝试将表名称从 _user 更改为不带下划线的名称,例如 user 或 app_user:

@Table(name = "app_user")

此更改还会影响 Hibernate 将用于 id 字段的 @GenerateValue 的序列名称。

此外,您使用的是 MySQL 的

org.hibernate.dialect.MySQLDialect
,但您的数据库是 H2。您应该为您的 H2 数据库使用适当的方言:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

0
投票

在您的应用程序属性文件中,只需包含

spring.jpa.hibernate.ddl-auto=更新 如果你想自动生成表格

© www.soinside.com 2019 - 2024. All rights reserved.