【问题标题】:Unable to connect IBMi machine with Spring Data & JPA无法将 IBMi 机器与 Spring Data & JPA 连接
【发布时间】:2021-06-24 17:27:15
【问题描述】:

尝试使用 Spring Data & JPA 连接 IBMi 机器,但它正在生成错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; 
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError: Receiver class com.ibm.as400.access.AS400JDBCConnectionImpl does not define or inherit an implementation of the resolved method 'abstract boolean isValid(int)' of interface java.sql.Connection.
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.8.jar:5.3.8]
    at spring.security.as400.SpringSecurityDemoApplication2.main(SpringSecurityDemoApplication2.java:10) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError: Receiver class com.ibm.as400.access.AS400JDBCConnectionImpl does not define or inherit an implementation of the resolved method 'abstract boolean isValid(int)' of interface java.sql.Connection.
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.8.jar:5.3.8]
Caused by: java.lang.AbstractMethodError: Receiver class com.ibm.as400.access.AS400JDBCConnectionImpl does not define or inherit an implementation of the resolved method 'abstract boolean isValid(int)' of interface java.sql.Connection.
    at com.zaxxer.hikari.pool.PoolBase.checkValidationSupport(PoolBase.java:458) ~[HikariCP-3.4.5.jar:na]

该项目是一个入门项目,用于学习使用 JPA 连接 IBMi 机器的 Spring Data,但似乎 Spring Data 并没有为此提供最简单的方法。

我的项目类是:

  1. pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.7</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>Spring-Security-JT400</groupId>
        <artifactId>Security-JT400</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>Security-JT400</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            
            
            <dependency>
                <groupId>net.sf.jt400</groupId>
                <artifactId>jt400</artifactId>
                <version>10.6</version>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
  1. 配置
     @Configuration
        @EnableWebSecurity
        public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
    {
        @Autowired
        CustomUserDetailsService customUserDetailsService;
    
        @Bean
        AuthenticationProvider authenticationProvider()
        {
            DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
            provider.setUserDetailsService(customUserDetailsService);
            provider.setPasswordEncoder(new BCryptPasswordEncoder());
    
            return provider;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception
        {
            http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/home").hasAuthority("USER")
                .antMatchers("/admin").hasAuthority("ADMIN")
                .anyRequest().authenticated()
                .and()
                .httpBasic();
        }
    }
  1. CustomUserDetailsS​​ervice
    @Service
    public class CustomUserDetailsService implements UserDetailsService
    {
        @Autowired
        private UserRepository userRepository;
        
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
        {
            User user = userRepository.findByUsername(username);
            if (user == null)
            {
                throw new UsernameNotFoundException("User not found.");
            }
    
            return new CustomUserDetails(user);
        }
    }
    @Repository
    public interface UserRepository extends JpaRepository<User, Integer>
    {
        public User findByUsername(String username);
    }
    @RestController
    public class HomeController
    {
        @GetMapping("/home")
        public String home()
        {
            return "This is Home Page.";
        }
    
        @GetMapping("/admin")
        public String admin()
        {
            return "This is Admin Page.";
        }
        
    }
    public class CustomUserDetails implements UserDetails
    {
        private User user;
        
        public CustomUserDetails(User user)
        {
            super();
            this.user = user;
        }
    
        private static final long serialVersionUID = -228521734196009612L;
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities()
        {
            return Collections.singleton(new SimpleGrantedAuthority(user.getRole()));
        }
    
        @Override
        public String getPassword()
        {
            return user.getPassword();
        }
    
        @Override
        public String getUsername()
        {
            return user.getUsername();
        }
    
        @Override
        public boolean isAccountNonExpired()
        {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked()
        {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired()
        {
            return true;
        }
    
        @Override
        public boolean isEnabled()
        {
            return true;
        }
    }
    @Entity
    public class User
    {
        @Id
        private int id;
        private String username;
        private String password;
        private String role;
    }
    @SpringBootApplication
    public class SpringSecurityDemoApplication2 {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringSecurityDemoApplication2.class, args);
        }
    }
  1. application.properties
    spring.datasource.url=jdbc:as400://192.168.xx.xxx/;translate binary=true;prompt=false
    spring.datasource.username=USERNAME
    spring.datasource.password=PASSWORD
    spring.datasource.driver-class-name=com.ibm.as400.access.AS400JDBCDriver
    spring.jpa.database-platform=org.hibernate.dialect.DB2400Dialect

注意:使用相同的类并在application.properties中进行更改,可以连接MYSQL数据库。

【问题讨论】:

  • 错误指出:Receiver class com.ibm.as400.access.AS400JDBCConnectionImpl does not define or inherit an implementation of the resolved method 'abstract boolean isValid(int)' of interface java.sql.Connection. 但是文档说 isValid(int) 在 jt400 10.6、10.4 等中实现,但我在 com 的源代码中没有看到这种方法。 ibm.as400.access.AS400JDBCConnection
  • 你解决了吗?

标签: java spring spring-boot spring-data-jpa spring-data


【解决方案1】:

尝试在@SpringBootApplication下方添加@EnableJpaRepositories注解

【讨论】:

  • 这与贴出的问题无关。
【解决方案2】:

我有同样的问题。问题是,abstract boolean isValid(int) 方法似乎没有实现,或者不能正常工作(我不确定)。基本上,它正在检查与 DB 的连接是否正常。 令人高兴的是,您可以将其更改为您自己的。在 Spring Boot 中只需添加到 application.propertiesspring.datasource.hikari.connection-test-query: values 1

对我来说 values 1 有效(我使用的是 AS400 DB2),但对于其他 DB,您可能需要使用不同的 check this answer

我有多个数据源,不幸的是,将它们添加到 application.properties 是不够的,我必须像这样在 PersistanceConfigurator 中设置它:

@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource as400DataSource() {
    HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder.create().build();
    dataSource.setConnectionTestQuery("values 1");
    return dataSource;
}

现在一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 2016-12-02
    • 2018-11-17
    • 2020-08-30
    • 1970-01-01
    • 2017-04-21
    相关资源
    最近更新 更多