簡體   English   中英

如何在沒有Spring Boot的情況下使用JPA存儲庫

[英]How to use JPA Repositories without Spring Boot

我有一個現有的spring 4項目(mvc,jdbc等),我試着把它移植到spring boot我不能。 (許多依賴性問題,沒有人無法解釋我怎么能這樣做)。 但現在我只想在現有項目中使用Spring Data JPA。 這是一個主要的pom依賴:

<properties>
        <jetty.version>9.3.5.v20151012</jetty.version>
        <spring.version>4.3.12.RELEASE</spring.version>
        <spring.boot.version>1.5.8.RELEASE</spring.boot.version>
        <spring.security.version>4.2.3.RELEASE</spring.security.version>
        <quartz.version>2.2.1</quartz.version>
        <slf4j.version>1.7.5</slf4j.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <hibernate-version>5.3.3.Final</hibernate-version>
    </properties>

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
            <version>${spring.boot.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-validation</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.jboss.logging</groupId>
                    <artifactId>jboss-logging</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-annotations</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-validator</artifactId>
                </exclusion>

            </exclusions>
        </dependency>
    <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>
<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate-version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate-version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.2.1.RELEASE</version>
        </dependency>

我有現有的配置,我使用entityManagerFactory Bean(在所有示例中使用)完成。 對DBConfig:

@Configuration
@ComponentScan("ru.testproject.*")
@EnableTransactionManagement
@EnableJpaRepositories("ru.testproject.*")
public class DatabaseConfig {

    @Value("${postgresql.address}")
    String address;
    @Value("${postgresql.database}")
    String database;
    @Value("${postgresql.user}")
    String user;
    @Value("${postgresql.password}")
    String password;
    @Value("${db.type}")
    String dbType;

    @Bean
    public DataSource dataSource() {

        if (DB_TYPE_POSTGRESQL.equalsIgnoreCase(dbType)) {
            return postresqlDataSource();
        } else {
            return derbyDataSource();
        }

    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        return dataSourceTransactionManager;
    }

    private HikariDataSource derbyDataSource() {

        try {
            String appHome = System.getProperty(Property.APP_HOME);

            Path path = Paths.get(appHome, DATABASE_NAME);
            String databaseName = path.toString();

            databaseName = StringUtils.replaceChars(databaseName, '\\', '/');

            Class.forName(DB.DB_DRIVER_DERBY).newInstance();

            EmbeddedDataSource embeddedDataSource = new EmbeddedDataSource();
            String dbName = databaseName;

            embeddedDataSource.setDatabaseName(dbName);
            embeddedDataSource.setCreateDatabase("create");

            embeddedDataSource.setUser("application");
            embeddedDataSource.setPassword("");

            HikariConfig config = new HikariConfig();
            config.setDataSource(embeddedDataSource);
            config.setMaximumPoolSize(10);
            config.setAutoCommit(true);

            HikariDataSource hikariDataSource = new HikariDataSource(config);

            return hikariDataSource;
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new IllegalStateException("error connection Derby");
        }

    }

    private HikariDataSource postresqlDataSource() {

        if (StringUtils.isBlank(address)
                || StringUtils.isBlank(database)
                || StringUtils.isBlank(user)
                || StringUtils.isBlank(password)) {
            throw new IllegalStateException("error params Postgresql");
        }

        HikariConfig config = new HikariConfig();
        String jdbcUrl = MessageFormat.format(POSTGRESQL, address, database);
        config.setJdbcUrl(jdbcUrl);
        config.setUsername(user);
        config.setPassword(password);
        config.setMaximumPoolSize(10);
        config.setAutoCommit(false);

        return new HikariDataSource(config);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws SQLException {

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("ru.testproject.hibernate.*");
        factory.setDataSource(dataSource());
        factory.afterPropertiesSet();
        factory.setPersistenceUnitName("test");
        return factory;
    }

}

用於測試的Derby數據庫。 但主數據庫類型是PostgreSQL和HikariCP。 我已經在項目中添加了HQL支持,它運行正常。 但是當我嘗試添加JAP存儲庫支持時,我遇到了很多問題。 我有實體:

@Entity
@Table(name = "users", schema = "public", catalog = "test")
public class Users {
    private int id;
    private String username;
    private String password;
    private String email;

    @Id
    @Column(name = "id", nullable = false)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "username", nullable = false, length = 64)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Basic
    @Column(name = "password", nullable = false, length = 64)
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Basic
    @Column(name = "email", nullable = false, length = 128)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Users that = (Users) o;
        return id == that.id &&
                Objects.equals(username, that.username) &&
                Objects.equals(password, that.password) &&
                Objects.equals(email, that.email);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, username, password, email);
    }
}

和存儲庫:

@Repository
public interface UsersRepository extends CrudRepository<Users, Long> {

    @Query("select b from Users b where b.username = :username")
    Users findByName(@Param("username") String username);
}

它只是一個測試存儲庫擴展了CrudRepository。 為了使用該存儲庫,我已經創建了實現服務:

@Service
public interface UserService {

    void delete(long id);
    Users getByName(String name);
    Optional<Users> getById(Long id);
    Users editUsers(Users user);
}

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UsersRepository usersRepository;

//    @PersistenceContext(unitName = "test")
//    private EntityManager em;

    @Override
    public void delete(long id) {
        usersRepository.deleteById(id);
    }

    @Override
    public Optional<Users> getById(Long id) {
        return usersRepository.findById(id);
    }

    @Override
    public Users getByName(String name) {
        return usersRepository.findByName(name);
    }

    @Override
    public Users editUsers(Users user) {
        return usersRepository.save(user);
    }
}

我正在使用這樣的存儲庫:

@Autowired
    private UserService service;
...
Users entry = service.getById(1L).get();

就這些。 我不使用Spring Boot(如上所述)並在應用程序因錯誤而失敗時啟動:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ru.testproject.config.DBConfig: 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.NoSuchFieldError: parallelCapableClassLoaderAvailable
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587)

如果我評論@EnableJpaRepositories注釋,我有以下錯誤:

Unsatisfied dependency expressed through field 'userServiceImpl'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'usersRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'ru.testproject.db.hibernate.repository.UsersRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

在第二個場景存儲庫是null,當然 - JPA repo的禁用..請,幫助! 我做錯了什么,我怎么能讓它有效? 我無法解決谷歌和互聯網的問題。 也許是因為我不明白根本問題是什么。

您似乎沒有在組件掃描中添加測試包ru.testproject.db.hibernate.repository。

感謝所有人的幫助! 我通過以下更改解決了我的問題:1)首先 - 我用更新的版本更新了spring-context依賴:

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.4.RELEASE</version>
    </dependency>

它解決了java.lang.NoClassDefFoundError:org / springframework / context / index / CandidateComponentsIndexLoader錯誤。 CandidateComponentsIndexLoader出現在spring-context 5.0.0之后。

2)我添加了

@EnableJpaRepositories(basePackages = {
        "ru.testproject.hibernate"
})
@PropertySource("classpath:testproject.properties")
@ComponentScan("ru.testproject.hibernate")

注釋。 以前的更改不會影響任何積極的變化。 1)它導致entityManagerFactory錯誤,我可以解決:

3)為entityManagerFactory設置packgeToScan

entityManagerFactoryBean.setPackagesToScan("ru.testproject.hibernate.entity");

與實體的路徑(在這種情況下的用戶)。

就這些。 現在存儲庫工作得很好。 謝謝你們!!!

ps:可能,現在我可以從春季靴子開始)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM