Я не могу получить свои данные из H2 в модульном тесте Jpa - PullRequest
0 голосов
/ 19 ноября 2018

Мне удалось проверить свои запросы в Jpa - это означает, что они выполняются, но они ничего не возвращают, и я не знаю почему. Кажется, что в моей таблице stockdata есть данные, потому что, если я пытаюсь вставить одни и те же данные дважды в мою таблицу, я получаю «Уникальный индекс или нарушение первичного ключа», поэтому я, похоже, подключаюсь к другой базе данных H2.

Вот мой код целиком, начиная с теста JUnit, который я пытаюсь заставить работать.

Если вы не видите проблемы, я все равно хотел бы получить любой вклад, который вы можете иметь, потому что я изучаю загрузку Spring и Spring одновременно и буду любить любые указатели! Спасибо!

// the unit test that fails - but should not (the list comes back empty)
package com.myorg.stockService.stockservice;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import com.myorg.stockService.entity.StockData;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = {StockServiceConfig.class})
public class StockServiceApplicationTests {

    @Autowired
    StockService stockService;

    @Test
    public void contextLoads() {

        //List<StockData> list = stockService.getAllDailyStockData("TNDM");

        List<StockData> list = stockService.findAll();
        assert(list.size() > 0);
    }

}

Класс сущности:

package com.myorg.stockService.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "stockdata",
        indexes = {@Index(name="symbol_interval_type_index", columnList="symbol,intervalType", unique=false)}
)
public class StockData extends AuditModel {

    private static final long serialVersionUID = 1L;

    public static final int DAILY=1;

    private StockKey key;

    @Column
    private float open;

    @Column
    private float high;

    @Column
    private float low;

    @Column
    private float close;

    @Column(columnDefinition="adjusted_close")
    private float adjustedClose;

    @Column
    private int volume;

    @Column(columnDefinition="dividend_amount")
    private float dividendAmount;

    @Column(columnDefinition="split_coefficient")
    private float splitCoefficient;

    public StockData() {}

    public StockData(StockKey key, float open, float high, float low, float close, float adjustedClose, int volume,
            float dividendAmount, float splitCoefficient) {
        super();
        this.key = key;
        this.open = open;
        this.high = high;
        this.low = low;
        this.close = close;
        this.adjustedClose = adjustedClose;
        this.volume = volume;
        this.dividendAmount = dividendAmount;
        this.splitCoefficient = splitCoefficient;
    }

    @Id
    public StockKey getKey() {
        return key;
    }
    public void setKey(StockKey key) {
        this.key = key;
    }
    public float getOpen() {
        return open;
    }
    public void setOpen(float open) {
        this.open = open;
    }
    public float getHigh() {
        return high;
    }
    public void setHigh(float high) {
        this.high = high;
    }
    public float getLow() {
        return low;
    }
    public void setLow(float low) {
        this.low = low;
    }
    public float getClose() {
        return close;
    }
    public void setClose(float close) {
        this.close = close;
    }
    public float getAdjustedClose() {
        return adjustedClose;
    }
    public void setAdjustedClose(float adjustedClose) {
        this.adjustedClose = adjustedClose;
    }
    public int getVolume() {
        return volume;
    }
    public void setVolume(int volume) {
        this.volume = volume;
    }
    public float getDividendAmount() {
        return dividendAmount;
    }
    public void setDividendAmount(float dividendAmount) {
        this.dividendAmount = dividendAmount;
    }
    public float getSplitCoefficient() {
        return splitCoefficient;
    }
    public void setSplitCoefficient(float splitCoefficient) {
        this.splitCoefficient = splitCoefficient;
    }

    @Override
    public String toString() {
        return "\nStockData [key=" + key + ", open=" + open + ", high=" + high + ", low=" + low + ", close=" + close
                + ", adjustedClose=" + adjustedClose + ", volume=" + volume + ", dividendAmount=" + dividendAmount
                + ", splitCoefficient=" + splitCoefficient + "]";
    }   
}

И его составной ключ:

package com.myorg.stockService.entity;

import java.io.Serializable;
import java.sql.Timestamp;

import javax.persistence.Embeddable;

// This is the composite key class for StockData

@Embeddable
public class StockKey implements Serializable {

    private static final long serialVersionUID = 1L;

    private String symbol;
    private int intervalType;
    private Timestamp ts;

    public StockKey(String symbol, int intervalType, Timestamp timestamp) {

        this.symbol = symbol;
        this.intervalType = intervalType;
        this.ts= timestamp;
    }

    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public int getIntervalType() {
        return intervalType;
    }
    public void setIntervalType(int intervalType) {
        this.intervalType = intervalType;
    }
    public Timestamp getTimestamp() {
        return ts;
    }
    public void setTimestamp(Timestamp timestamp) {
        this.ts = timestamp;
    }

}

Модель Audit для полноты:

package com.myorg.stockService.entity;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(
        value = {"createdAt", "updatedAt"},
        allowGetters = true
)
public abstract class AuditModel implements Serializable {

    private static final long serialVersionUID = 1L;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at", nullable = false, updatable = false)
    @CreatedDate
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated_at", nullable = false)
    @LastModifiedDate
    private Date updatedAt;

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }
}

Мой класс репо:

package com.myorg.stockService.repository;

import java.util.List;

import javax.transaction.Transactional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.myorg.stockService.entity.*;

@Repository
@Transactional
public interface StockRepository extends JpaRepository<StockData, StockKey> {

    //@PersistenceContext
    //EntityManager entityManager;

    @Query("Select s from StockData s where s.key.symbol = ?1 AND s.key.intervalType= ?2")
    public List<StockData> getAllStockData(@Param("symbol") String symbol, @Param("intervalType") int intervalType);

}

Класс обслуживания на складе, который мой тест JUnit использует для поискаAll из:

package com.myorg.stockService.stockservice;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.myorg.stockService.entity.StockData;
import com.myorg.stockService.repository.StockRepository;


@Service
public class StockService {

    @Autowired
    private StockRepository stockRepository;

    public List<StockData> getAllDailyStockData(String symbol) {

        return stockRepository.getAllStockData(symbol, 1);
    }

    public List<StockData> findAll() {

        return stockRepository.findAll();
    }
}

Класс приложения. Обратите внимание, что assert также не работает в методе run:

package com.myorg.stockService.stockservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;

@SpringBootApplication
@EntityScan(basePackages = {"com.myorg.stockService"})
public class StockServiceApplication implements CommandLineRunner {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public static void main(String[] args) {
        SpringApplication.run(StockServiceApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        List<StockData> list = stockService.findAll();
        assert(list.size() > 0);
    }
}

3 файла в моей папке src / main / resources:

application.properties:

spring.h2.console.enabled=true
spring.jpa.show-sql=true
logging.level.root=warn

data.sql -> Примечание. Я также добавил этот файл в src / test / resources, но это не помогло

INSERT INTO stockdata(symbol,interval_type,ts,open,high,low,close,adjusted_close,volume,dividend_amount, split_coefficient) VALUES
    ('TNDM', 1, parsedatetime('2018-09-14', 'yyyy-MM-dd'), 112.1200, 113.7250, 112.1200, 112.9100, 112.4174, 26055620, 0.0000, 1.0000);

schema.sql:

// schema.sql:
CREATE TABLE stockdata (

    symbol VARCHAR NOT NULL,
    interval_type INT NOT NULL,
    ts TIMESTAMP NOT NULL,
    open DOUBLE NOT NULL,
    high DOUBLE NOT NULL,
    low DOUBLE NOT NULL,
    close DOUBLE NOT NULL,
    adjusted_close DOUBLE NOT NULL,
    volume INT NOT NULL,
    dividend_amount DOUBLE NOT NULL,
    split_coefficient DOUBLE NOT NULL,
    PRIMARY KEY(symbol, interval_type, ts)
);

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.myorg.stockService</groupId>
    <artifactId>stock-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>stock-service</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <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-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-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 Ответ

0 голосов
/ 19 ноября 2018

Похоже, было несколько проблем с опубликованным кодом, когда я его пробовал.

  1. Я не мог видеть StockServiceConfig.class, используемый для ContextConfiguration в тестовом классе.Поэтому я использовал StockServiceApplication.class.Я также переместил это на уровень структуры пакета, чтобы компонент сканировал, чтобы найти репозиторий.

  2. Я не думаю, что schema.sql запускается.Это просто позволяет hibernate сделать ddl-auto.Установите следующее в application.properties, чтобы остановить это:

    spring.jpa.hibernate.ddl-auto=none
    
  3. Перед CREATE TABLE в schema.sql есть комментарий.Sringboot, казалось, объединял все это вместе и рассматривал все это как одну строку комментариев.Добавьте точку с запятой после комментария:

    // schema.sql:;
    CREATE TABLE stockdata (
    
       symbol VARCHAR NOT NULL,
       ... etc
    
  4. Ваш StockKey имеет getTimestamp и setTimestamp, тогда как поле равно ts (что соответствует schema.sql).Измените их на getTs и setTs или предоставьте подходящие аннотации для имени столбца.Также необходим конструктор по умолчанию.

  5. StockData расширяет AuditModel, но ваш schema.sql не определяет ни один из столбцов в AuditModel.Либо определите столбцы, либо не расширяйте AuditModel.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...