pom文件
java
复制代码
<?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>3.5.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.mqq.dd</groupId>
<artifactId>dolphinDB-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dolphinDB-demo</name>
<description>dolphinDB-demo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.dolphindb/dolphindb-javaapi -->
<dependency>
<groupId>com.dolphindb</groupId>
<artifactId>dolphindb-javaapi</artifactId>
<version>3.00.2.2</version>
</dependency>
<dependency>
<groupId>com.dolphindb</groupId>
<artifactId>jdbc</artifactId>
<version>3.00.2.2</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>enforce-java</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[17,)</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml文件
java
复制代码
spring:
application:
name: dolphinDB-demo
dolphindb:
host: 170.21.12.14
port: 8858
username: admin
password: 123456
connect-timeout: 5000
database: dfs://db
table: tb
DolphinDBConfig配置文件
java
复制代码
package com.mqq.dd.config;
import com.xxdb.DBConnection;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
@Configuration
public class DolphinDBConfig {
@Value("${dolphindb.host}")
private String host;
@Value("${dolphindb.port}")
private int port;
@Value("${dolphindb.username}")
private String username;
@Value("${dolphindb.password}")
private String password;
@Bean(destroyMethod = "close")
public DBConnection dolphinDBConnection() throws IOException {
DBConnection dbConnection = new DBConnection();
dbConnection.connect(host, port, username, password);
return dbConnection;
}
}
DolphinDbDemoApplication 启动类
java
复制代码
package com.mqq.dd;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DolphinDbDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DolphinDbDemoApplication.class, args);
}
}
entity 实体类
java
复制代码
package com.mqq.dd.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
public class TradeSummary implements Serializable {
// 交易时间
private LocalDateTime tradeTime;
// 股票id
private String securityId;
private long totalVolumeTrade;
private Double totalValueTrade;
public TradeSummary() {
}
public TradeSummary(LocalDateTime tradeTime, String securityId, long totalVolumeTrade, Double totalValueTrade) {
this.tradeTime = tradeTime;
this.securityId = securityId;
this.totalVolumeTrade = totalVolumeTrade;
this.totalValueTrade = totalValueTrade;
}
public LocalDateTime getTradeTime() {
return tradeTime;
}
public void setTradeTime(LocalDateTime tradeTime) {
this.tradeTime = tradeTime;
}
public String getSecurityId() {
return securityId;
}
public void setSecurityId(String securityId) {
this.securityId = securityId;
}
public long getTotalVolumeTrade() {
return totalVolumeTrade;
}
public void setTotalVolumeTrade(long totalVolumeTrade) {
this.totalVolumeTrade = totalVolumeTrade;
}
public Double getTotalValueTrade() {
return totalValueTrade;
}
public void setTotalValueTrade(Double totalValueTrade) {
this.totalValueTrade = totalValueTrade;
}
}
Controller
java
复制代码
package com.mqq.dd.controller;
import com.mqq.dd.entity.TradeSummary;
import com.mqq.dd.service.DolphinDBService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.List;
@RestController
public class DolphinDBController {
@Autowired
private DolphinDBService dolphinDBService;
@GetMapping("/trades")
public List<TradeSummary> getTrades(
@RequestParam String securityId,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime
) throws Exception {
return dolphinDBService.queryTradeData(securityId, startTime, endTime);
}
@PostMapping("/trades")
public void insertTrade(@RequestBody TradeSummary trade) throws Exception {
dolphinDBService.insertTrade(trade);
}
@PostMapping("/trades/batch")
public void insertTrades(@RequestBody List<TradeSummary> trades) throws Exception {
dolphinDBService.insertTrades(trades);
}
@PutMapping("/trades")
public void updateTrade(@RequestBody TradeSummary trade) throws Exception {
dolphinDBService.updateTrade(trade);
}
@DeleteMapping("/trades")
public void deleteTrade(
@RequestParam String securityId,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime tradeTime
) throws Exception {
dolphinDBService.deleteTrade(securityId, tradeTime);
}
}
Service
java
复制代码
package com.mqq.dd.service;
import com.mqq.dd.entity.TradeSummary;
import com.mqq.dd.util.DolphinDBTradeUtils;
import com.xxdb.DBConnection;
import com.xxdb.data.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Service
public class DolphinDBService {
@Autowired
private DBConnection connection;
@Value("${dolphindb.database:dfs://db}")
private String database;
@Value("${dolphindb.table:tb}")
private String tableName;
/**
* 查询某证券在指定时间范围内的成交汇总
*/
public List<TradeSummary> queryTradeData(String securityId, LocalDateTime start, LocalDateTime end) throws Exception {
if (securityId == null || securityId.isBlank()) {
throw new IllegalArgumentException("securityId is blank");
}
if (start == null || end == null) {
throw new IllegalArgumentException("start/end is null");
}
String script = ""
+ "select TradeTime, SecurityID, TotalVolumeTrade, TotalValueTrade "
+ "from loadTable('" + DolphinDBTradeUtils.escapeSingleQuoted(database) + "', '" + DolphinDBTradeUtils.escapeSingleQuoted(tableName) + "') "
+ "where SecurityID = " + DolphinDBTradeUtils.toDdbStringLiteral(securityId) + " "
+ "and TradeTime >= " + DolphinDBTradeUtils.toDdbTimestampLiteral(start) + " "
+ "and TradeTime <= " + DolphinDBTradeUtils.toDdbTimestampLiteral(end);
Entity result = connection.run(script);
if (!(result instanceof BasicTable)) {
throw new RuntimeException("Query did not return a table");
}
BasicTable table = (BasicTable) result;
int rows = table.rows();
List<TradeSummary> list = new ArrayList<>();
BasicTimestampVector timeCol = (BasicTimestampVector) table.getColumn("TradeTime");
BasicStringVector secCol = (BasicStringVector) table.getColumn("SecurityID");
BasicLongVector volCol = (BasicLongVector) table.getColumn("TotalVolumeTrade");
BasicDoubleVector valCol = (BasicDoubleVector) table.getColumn("TotalValueTrade");
for (int i = 0; i < rows; i++) {
LocalDateTime tradeTime = timeCol.getTimestamp(i);
String secId = secCol.getString(i);
long volume = volCol.getLong(i);
Double value = valCol.isNull(i) ? null : valCol.getDouble(i);
list.add(new TradeSummary(tradeTime, secId, volume, value));
}
return list;
}
public void insertTrade(TradeSummary trade) throws Exception {
insertTrades(List.of(trade));
}
public void insertTrades(List<TradeSummary> trades) throws Exception {
if (trades == null || trades.isEmpty()) {
return;
}
Entity inMemoryTable = DolphinDBTradeUtils.toTradeSummaryTable(trades);
String script = "tableInsert{loadTable('" + DolphinDBTradeUtils.escapeSingleQuoted(database) + "', '" + DolphinDBTradeUtils.escapeSingleQuoted(tableName) + "')}";
connection.run(script, List.of(inMemoryTable));
}
/**
* Update a trade row by (SecurityID, TradeTime).
*/
public void updateTrade(TradeSummary trade) throws Exception {
if (trade == null) {
throw new IllegalArgumentException("trade is null");
}
if (trade.getTradeTime() == null) {
throw new IllegalArgumentException("tradeTime is null");
}
if (trade.getSecurityId() == null || trade.getSecurityId().isBlank()) {
throw new IllegalArgumentException("securityId is blank");
}
String script = ""
+ "t=loadTable('" + DolphinDBTradeUtils.escapeSingleQuoted(database) + "', '" + DolphinDBTradeUtils.escapeSingleQuoted(tableName) + "');"
+ "update t set "
+ "TotalVolumeTrade=" + trade.getTotalVolumeTrade() + ","
+ "TotalValueTrade=" + (trade.getTotalValueTrade() == null ? "NULL" : trade.getTotalValueTrade())
+ " where SecurityID=" + DolphinDBTradeUtils.toDdbStringLiteral(trade.getSecurityId())
+ " and TradeTime=" + DolphinDBTradeUtils.toDdbTimestampLiteral(trade.getTradeTime());
connection.run(script);
}
/**
* Delete a trade row by (SecurityID, TradeTime).
*/
public void deleteTrade(String securityId, LocalDateTime tradeTime) throws Exception {
if (tradeTime == null) {
throw new IllegalArgumentException("tradeTime is null");
}
if (securityId == null || securityId.isBlank()) {
throw new IllegalArgumentException("securityId is blank");
}
String script = ""
+ "t=loadTable('" + DolphinDBTradeUtils.escapeSingleQuoted(database) + "', '" + DolphinDBTradeUtils.escapeSingleQuoted(tableName) + "');"
+ "delete from t where SecurityID=" + DolphinDBTradeUtils.toDdbStringLiteral(securityId)
+ " and TradeTime=" + DolphinDBTradeUtils.toDdbTimestampLiteral(tradeTime);
connection.run(script);
}
util 工具类
java
复制代码
package com.mqq.dd.util;
import com.mqq.dd.entity.TradeSummary;
import com.xxdb.data.BasicDoubleVector;
import com.xxdb.data.BasicLongVector;
import com.xxdb.data.BasicStringVector;
import com.xxdb.data.BasicTable;
import com.xxdb.data.BasicTimestampVector;
import com.xxdb.data.Entity;
import com.xxdb.data.Vector;
import java.time.LocalDateTime;
import java.util.List;
public final class DolphinDBTradeUtils {
private DolphinDBTradeUtils() {
}
public static String escapeSingleQuoted(String s) {
if (s == null) {
return "";
}
return s.replace("'", "''");
}
/**
* DolphinDB string literal uses double quotes.
*/
public static String toDdbStringLiteral(String s) {
if (s == null) {
return "NULL";
}
return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
}
/**
* DolphinDB TIMESTAMP literal: yyyy.MM.ddTHH:mm:ss.SSS (no quotes).
*/
public static String toDdbTimestampLiteral(LocalDateTime t) {
if (t == null) {
throw new IllegalArgumentException("timestamp is null");
}
return String.format(
"%04d.%02d.%02dT%02d:%02d:%02d.%03d",
t.getYear(), t.getMonthValue(), t.getDayOfMonth(),
t.getHour(), t.getMinute(), t.getSecond(),
t.getNano() / 1_000_000
);
}
/**
* Build an in-memory DolphinDB table for tableInsert.
*/
public static Entity toTradeSummaryTable(List<TradeSummary> dataList) {
if (dataList == null) {
throw new IllegalArgumentException("dataList is null");
}
int n = dataList.size();
BasicTimestampVector timeVec = new BasicTimestampVector(n);
BasicStringVector secVec = new BasicStringVector(n);
BasicLongVector volVec = new BasicLongVector(n);
BasicDoubleVector valVec = new BasicDoubleVector(n);
for (int i = 0; i < n; i++) {
TradeSummary t = dataList.get(i);
if (t == null) {
throw new IllegalArgumentException("trade is null at index " + i);
}
if (t.getTradeTime() == null) {
throw new IllegalArgumentException("tradeTime is null at index " + i);
}
if (t.getSecurityId() == null || t.getSecurityId().isBlank()) {
throw new IllegalArgumentException("securityId is blank at index " + i);
}
timeVec.setTimestamp(i, t.getTradeTime());
secVec.setString(i, t.getSecurityId());
volVec.setLong(i, t.getTotalVolumeTrade());
if (t.getTotalValueTrade() == null) {
valVec.setNull(i);
} else {
valVec.setDouble(i, t.getTotalValueTrade());
}
}
return new BasicTable(
List.of("TradeTime", "SecurityID", "TotalVolumeTrade", "TotalValueTrade"),
List.<Vector>of(timeVec, secVec, volVec, valVec)
);
}
}