Merge pull request #43 from vran-dev/feature/databaseTypes

feature: support custom database types
This commit is contained in:
vran 2022-03-12 11:13:17 +08:00 committed by GitHub
commit 3ceb51748e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1852 additions and 62 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
.gradle/**
**/build/**
.idea/**
**/.DS_Store
**/.DS_Store
drivers/**

View File

@ -0,0 +1,72 @@
package com.databasir.api;
import com.databasir.api.validator.DatabaseTypeValidator;
import com.databasir.common.JsonData;
import com.databasir.core.domain.database.data.*;
import com.databasir.core.domain.database.service.DatabaseTypeService;
import com.databasir.core.domain.log.annotation.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
import static org.springframework.data.domain.Sort.Direction.DESC;
@RequiredArgsConstructor
@Validated
@RestController
public class DatabaseTypeController {
private final DatabaseTypeService databaseTypeService;
private final DatabaseTypeValidator databaseTypeValidator;
@GetMapping(Routes.DatabaseType.LIST_SIMPLE)
public JsonData<List<String>> listSimpleDatabaseTypes() {
List<String> types = databaseTypeService.listSimpleDatabaseTypes();
return JsonData.ok(types);
}
@GetMapping(Routes.DatabaseType.LIST_PAGE)
public JsonData<Page<DatabaseTypePageResponse>> listPage(@PageableDefault(sort = "id", direction = DESC)
Pageable page,
DatabaseTypePageCondition condition) {
Page<DatabaseTypePageResponse> data = databaseTypeService.findByPage(page, condition);
return JsonData.ok(data);
}
@PostMapping(Routes.DatabaseType.CREATE)
@Operation(module = Operation.Modules.DATABASE_TYPE, name = "创建数据库类型")
public JsonData<Integer> create(@RequestBody @Valid DatabaseTypeCreateRequest request) {
databaseTypeValidator.isValidUrlPattern(request.getUrlPattern());
Integer id = databaseTypeService.create(request);
return JsonData.ok(id);
}
@PatchMapping(Routes.DatabaseType.UPDATE)
@Operation(module = Operation.Modules.DATABASE_TYPE, name = "更新数据库类型")
public JsonData<Void> update(@RequestBody @Valid DatabaseTypeUpdateRequest request) {
databaseTypeValidator.isValidUrlPattern(request.getUrlPattern());
databaseTypeService.update(request);
return JsonData.ok();
}
@DeleteMapping(Routes.DatabaseType.DELETE_ONE)
@Operation(module = Operation.Modules.DATABASE_TYPE, name = "删除数据库类型")
public JsonData<Void> delete(@PathVariable Integer id) {
databaseTypeService.deleteById(id);
return JsonData.ok();
}
@GetMapping(Routes.DatabaseType.GET_ONE)
public JsonData<DatabaseTypeDetailResponse> getOne(@PathVariable Integer id) {
Optional<DatabaseTypeDetailResponse> data = databaseTypeService.selectOne(id);
return JsonData.ok(data);
}
}

View File

@ -130,4 +130,19 @@ public interface Routes {
String GET_ONE = BASE + "/oauth2_apps/{id}";
}
}
interface DatabaseType {
String LIST_SIMPLE = BASE + "/simple_database_types";
String LIST_PAGE = BASE + "/database_types";
String GET_ONE = BASE + "/database_types/{id}";
String DELETE_ONE = BASE + "/database_types/{id}";
String UPDATE = BASE + "/database_types";
String CREATE = BASE + "/database_types";
}
}

View File

@ -0,0 +1,23 @@
package com.databasir.api.validator;
import com.databasir.core.domain.DomainErrors;
import org.springframework.stereotype.Component;
@Component
public class DatabaseTypeValidator {
public void isValidUrlPattern(String urlPattern) {
if (urlPattern == null) {
throw DomainErrors.INVALID_DATABASE_TYPE_URL_PATTERN.exception("url pattern 不能为空");
}
if (!urlPattern.contains("{{jdbc.protocol}}")) {
throw DomainErrors.INVALID_DATABASE_TYPE_URL_PATTERN.exception("必须包含变量{{jdbc.protocol}}");
}
if (!urlPattern.contains("{{db.url}}")) {
throw DomainErrors.INVALID_DATABASE_TYPE_URL_PATTERN.exception("必须包含变量{{db.url}}不能为空");
}
if (!urlPattern.contains("{{db.name}}")) {
throw DomainErrors.INVALID_DATABASE_TYPE_URL_PATTERN.exception("必须包含变量{{db.name}}不能为空");
}
}
}

View File

@ -1,10 +1,11 @@
server.port=8080
logging.level.org.jooq=INFO
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/databasir
spring.jooq.sql-dialect=mysql
# flyway
spring.flyway.enabled=true
spring.flyway.baseline-on-migrate=true
spring.flyway.locations=classpath:db/migration
# db
databasir.db.url=localhost:3306
databasir.db.username=root
databasir.db.password=123456
databasir.db.driver-directory=drivers

View File

@ -1 +1 @@
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir-frontend</title><script defer="defer" type="module" src="/js/chunk-vendors.45746587.js"></script><script defer="defer" type="module" src="/js/app.58f35973.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.757c1ef3.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.54c3660b.js" nomodule></script><script defer="defer" src="/js/app-legacy.ae769f77.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir-frontend</title><script defer="defer" type="module" src="/js/chunk-vendors.45746587.js"></script><script defer="defer" type="module" src="/js/app.21cfd672.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.757c1ef3.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.54c3660b.js" nomodule></script><script defer="defer" src="/js/app-legacy.f867641a.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
package com.databasir.core.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// 支持中文编码
restTemplate.getMessageConverters().set(1,
new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//单位为ms
factory.setReadTimeout(1000 * 30);
//单位为ms
factory.setConnectTimeout(1000 * 5);
return factory;
}
}

View File

@ -27,7 +27,12 @@ public enum DomainErrors implements DatabasirErrors {
INVALID_CRON_EXPRESSION("A_10012", "不合法的 cron 表达式"),
REGISTRATION_ID_DUPLICATE("A_10013", "应用注册 ID 不能重复"),
REGISTRATION_ID_NOT_FOUND("A_10014", "应用 ID 不存在"),
MISS_REQUIRED_PARAMETERS("A_10015", "缺少必填参数");
MISS_REQUIRED_PARAMETERS("A_10015", "缺少必填参数"),
DATABASE_TYPE_NAME_DUPLICATE("A_10016", "数据库类型名已存在"),
MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE("A_10017", "禁止修改系统默认数据库类型"),
DOWNLOAD_DRIVER_ERROR("A_10018", "驱动下载失败"),
INVALID_DATABASE_TYPE_URL_PATTERN("A_10019", "不合法的 url pattern"),
;
private final String errCode;
@ -46,6 +51,6 @@ public enum DomainErrors implements DatabasirErrors {
}
public DatabasirException exception(String s) {
return exception(s, (Throwable) null);
return exception(s, null);
}
}

View File

@ -0,0 +1,20 @@
package com.databasir.core.domain.database.converter;
import com.databasir.core.domain.database.data.DatabaseTypeCreateRequest;
import com.databasir.core.domain.database.data.DatabaseTypeDetailResponse;
import com.databasir.core.domain.database.data.DatabaseTypePageResponse;
import com.databasir.core.domain.database.data.DatabaseTypeUpdateRequest;
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface DatabaseTypePojoConverter {
DatabaseTypePojo of(DatabaseTypeCreateRequest request);
DatabaseTypePojo of(DatabaseTypeUpdateRequest request);
DatabaseTypeDetailResponse toDetailResponse(DatabaseTypePojo data);
DatabaseTypePageResponse toPageResponse(DatabaseTypePojo pojo, Integer projectCount);
}

View File

@ -0,0 +1,30 @@
package com.databasir.core.domain.database.data;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class DatabaseTypeCreateRequest {
@NotBlank
private String databaseType;
private String icon;
@NotBlank
private String description;
@NotBlank
private String jdbcDriverFileUrl;
@NotBlank
private String jdbcDriverClassName;
@NotBlank
private String jdbcProtocol;
@NotBlank
private String urlPattern;
}

View File

@ -0,0 +1,33 @@
package com.databasir.core.domain.database.data;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class DatabaseTypeDetailResponse {
private Integer id;
private String databaseType;
private String icon;
private String description;
private String jdbcDriverFileUrl;
private String jdbcDriverClassName;
private String jdbcProtocol;
private String urlPattern;
private Boolean deleted;
private Integer deletedToken;
private LocalDateTime updateAt;
private LocalDateTime createAt;
}

View File

@ -0,0 +1,26 @@
package com.databasir.core.domain.database.data;
import com.databasir.dao.Tables;
import lombok.Data;
import org.jooq.Condition;
import org.jooq.impl.DSL;
import java.util.ArrayList;
import java.util.List;
@Data
public class DatabaseTypePageCondition {
private String databaseTypeContains;
public Condition toCondition() {
List<Condition> conditions = new ArrayList<>();
conditions.add(Tables.DATABASE_TYPE.DELETED.eq(false));
if (databaseTypeContains != null && !databaseTypeContains.trim().equals("")) {
conditions.add(Tables.DATABASE_TYPE.DATABASE_TYPE_.containsIgnoreCase(databaseTypeContains));
}
return conditions.stream()
.reduce(Condition::and)
.orElse(DSL.trueCondition());
}
}

View File

@ -0,0 +1,35 @@
package com.databasir.core.domain.database.data;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class DatabaseTypePageResponse {
private Integer id;
private String databaseType;
private String icon;
private String description;
private String jdbcDriverFileUrl;
private String jdbcDriverClassName;
private String jdbcProtocol;
private Boolean deleted;
private Integer deletedToken;
private Integer projectCount;
private String urlPattern;
private LocalDateTime updateAt;
private LocalDateTime createAt;
}

View File

@ -0,0 +1,33 @@
package com.databasir.core.domain.database.data;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class DatabaseTypeUpdateRequest {
@NotNull
private Integer id;
@NotBlank
private String databaseType;
private String icon;
@NotBlank
private String description;
@NotBlank
private String jdbcDriverFileUrl;
@NotBlank
private String jdbcDriverClassName;
@NotBlank
private String jdbcProtocol;
@NotBlank
private String urlPattern;
}

View File

@ -0,0 +1,103 @@
package com.databasir.core.domain.database.service;
import com.databasir.core.domain.DomainErrors;
import com.databasir.core.domain.database.converter.DatabaseTypePojoConverter;
import com.databasir.core.domain.database.data.*;
import com.databasir.core.infrastructure.connection.DatabaseTypes;
import com.databasir.core.infrastructure.driver.DriverResources;
import com.databasir.dao.impl.DatabaseTypeDao;
import com.databasir.dao.impl.ProjectDao;
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class DatabaseTypeService {
private final DriverResources driverResources;
private final DatabaseTypeDao databaseTypeDao;
private final ProjectDao projectDao;
private final DatabaseTypePojoConverter databaseTypePojoConverter;
public Integer create(DatabaseTypeCreateRequest request) {
DatabaseTypePojo pojo = databaseTypePojoConverter.of(request);
try {
return databaseTypeDao.insertAndReturnId(pojo);
} catch (DuplicateKeyException e) {
throw DomainErrors.DATABASE_TYPE_NAME_DUPLICATE.exception();
}
}
@Transactional
public void update(DatabaseTypeUpdateRequest request) {
databaseTypeDao.selectOptionalById(request.getId()).ifPresent(data -> {
if (DatabaseTypes.has(data.getDatabaseType())) {
throw DomainErrors.MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE.exception();
}
DatabaseTypePojo pojo = databaseTypePojoConverter.of(request);
try {
databaseTypeDao.updateById(pojo);
} catch (DuplicateKeyException e) {
throw DomainErrors.DATABASE_TYPE_NAME_DUPLICATE.exception();
}
// 名称修改下载地址修改需要删除原有的 driver
if (!Objects.equals(request.getDatabaseType(), data.getDatabaseType())
|| !Objects.equals(request.getJdbcDriverFileUrl(), data.getJdbcDriverFileUrl())) {
driverResources.delete(data.getDatabaseType());
}
});
}
public void deleteById(Integer id) {
databaseTypeDao.selectOptionalById(id).ifPresent(data -> {
if (DatabaseTypes.has(data.getDatabaseType())) {
throw DomainErrors.MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE.exception();
}
databaseTypeDao.deleteById(id);
driverResources.delete(data.getDatabaseType());
});
}
public Page<DatabaseTypePageResponse> findByPage(Pageable page,
DatabaseTypePageCondition condition) {
Page<DatabaseTypePojo> pageData = databaseTypeDao.selectByPage(page, condition.toCondition());
List<String> databaseTypes = pageData.map(DatabaseTypePojo::getDatabaseType).toList();
Map<String, Integer> projectCountMapByDatabaseType = projectDao.countByDatabaseTypes(databaseTypes);
return pageData
.map(data -> {
Integer count = projectCountMapByDatabaseType.getOrDefault(data.getDatabaseType(), 0);
return databaseTypePojoConverter.toPageResponse(data, count);
});
}
public List<String> listSimpleDatabaseTypes() {
return databaseTypeDao.selectAll()
.stream()
.map(DatabaseTypePojo::getDatabaseType)
.collect(Collectors.toList());
}
public Optional<DatabaseTypeDetailResponse> selectOne(Integer id) {
return databaseTypeDao.selectOptionalById(id)
.map(databaseTypePojoConverter::toDetailResponse);
}
}

View File

@ -107,7 +107,18 @@ public class DocumentService {
documentPojoConverter.toColumnPojo(docId, tableMetaId, table.getColumns());
tableColumnDocumentDao.batchInsert(tableColumnMetas);
List<TableIndexDocumentPojo> tableIndexMetas =
documentPojoConverter.toIndexPojo(docId, tableMetaId, table.getIndexes());
documentPojoConverter.toIndexPojo(docId, tableMetaId, table.getIndexes())
.stream()
.filter(index -> {
if (index.getName() != null) {
return true;
} else {
log.warn("ignore table {} index {}, cause name is null", table.getName(), index);
return false;
}
})
.collect(Collectors.toList());
tableIndexDocumentDao.batchInsert(tableIndexMetas);
List<TableTriggerDocumentPojo> tableTriggerMetas =
documentPojoConverter.toTriggerPojo(docId, tableMetaId, table.getTriggers());

View File

@ -35,6 +35,7 @@ public @interface Operation {
String GROUP = "group";
String LOGIN_APP = "login_app";
String SETTING = "setting";
String DATABASE_TYPE = "database_type";
}
interface Types {

View File

@ -0,0 +1,88 @@
package com.databasir.core.infrastructure.connection;
import com.databasir.core.domain.DomainErrors;
import com.databasir.core.infrastructure.driver.DriverResources;
import com.databasir.dao.impl.DatabaseTypeDao;
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;
@Component
@RequiredArgsConstructor
@Slf4j
@Order
public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactory {
private final DatabaseTypeDao databaseTypeDao;
private final DriverResources driverResources;
@Override
public boolean support(String databaseType) {
return databaseTypeDao.existsByDatabaseType(databaseType);
}
@Override
public Connection getConnection(Context context) throws SQLException {
DatabaseTypePojo type = databaseTypeDao.selectByDatabaseType(context.getDatabaseType());
File driverFile;
try {
driverFile = driverResources.download(context.getDatabaseType(), type.getJdbcDriverFileUrl());
} catch (IOException e) {
log.error("download driver error " + context, e);
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
}
URLClassLoader loader = null;
try {
loader = new URLClassLoader(
new URL[]{
driverFile.toURI().toURL()
},
this.getClass().getClassLoader()
);
} catch (MalformedURLException e) {
log.error("load driver error " + context, e);
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage());
}
Class<?> clazz = null;
Driver driver = null;
try {
clazz = Class.forName(type.getJdbcDriverClassName(), true, loader);
driver = (Driver) clazz.getConstructor().newInstance();
} catch (ClassNotFoundException e) {
log.error("init driver error", e);
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常, 请检查 Driver name" + e.getMessage());
} catch (InvocationTargetException
| InstantiationException
| IllegalAccessException
| NoSuchMethodException e) {
log.error("init driver error", e);
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常:" + e.getMessage());
}
String urlPattern = type.getUrlPattern();
String jdbcUrl = urlPattern.replace("{{jdbc.protocol}}", type.getJdbcProtocol())
.replace("{{db.url}}", context.getUrl())
.replace("{{db.name}}", context.getSchema());
Properties info = new Properties();
info.put("user", context.getUsername());
info.put("password", context.getPassword());
return driver.connect(jdbcUrl, info);
}
}

View File

@ -1,5 +1,8 @@
package com.databasir.core.infrastructure.connection;
import lombok.Builder;
import lombok.Data;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
@ -8,9 +11,22 @@ public interface DatabaseConnectionFactory {
boolean support(String databaseType);
Connection getConnection(String username,
String password,
String url,
String schema,
Properties properties) throws SQLException;
Connection getConnection(Context context) throws SQLException;
@Builder
@Data
class Context {
private String databaseType;
private String username;
private String password;
private String url;
private String schema;
private Properties properties;
}
}

View File

@ -32,11 +32,19 @@ public class DatabaseConnectionService {
Properties info = new Properties();
dataSourceProperties.forEach(prop -> info.put(prop.getKey(), prop.getValue()));
try {
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
.username(username)
.password(password)
.url(url)
.schema(dataSource.getDatabaseName())
.properties(info)
.databaseType(dataSource.getDatabaseType())
.build();
return factories.stream()
.filter(factory -> factory.support(dataSource.getDatabaseType()))
.findFirst()
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
.getConnection(username, password, url, dataSource.getDatabaseName(), info);
.getConnection(context);
} catch (SQLException e) {
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
}
@ -49,11 +57,19 @@ public class DatabaseConnectionService {
String databaseType,
Properties properties) {
try {
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
.username(username)
.password(password)
.url(url)
.schema(databaseName)
.properties(properties)
.databaseType(databaseType)
.build();
factories.stream()
.filter(factory -> factory.support(databaseType))
.findFirst()
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
.getConnection(username, password, url, databaseName, properties);
.getConnection(context);
} catch (SQLException e) {
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
}

View File

@ -1,10 +1,19 @@
package com.databasir.core.infrastructure.connection;
import java.util.Objects;
public interface DatabaseTypes {
String MYSQL = "mysql";
String POSTGRESQL = "postgresql";
String ORACLE = "oracle";
static boolean has(String name) {
if (name == null) {
return false;
}
return Objects.equals(MYSQL, name.toLowerCase())
|| Objects.equals(POSTGRESQL, name.toLowerCase());
}
}

View File

@ -1,5 +1,6 @@
package com.databasir.core.infrastructure.connection;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.sql.Connection;
@ -8,6 +9,7 @@ import java.sql.SQLException;
import java.util.Properties;
@Component
@Order(1)
public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory {
@Override
@ -16,11 +18,7 @@ public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory
}
@Override
public Connection getConnection(String username,
String password,
String url,
String schema,
Properties properties) throws SQLException {
public Connection getConnection(Context context) throws SQLException {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
@ -28,10 +26,10 @@ public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory
}
Properties info = new Properties();
info.put("user", username);
info.put("password", password);
info.putAll(properties);
String jdbcUrl = "jdbc:mysql://" + url + "/" + schema;
info.put("user", context.getUsername());
info.put("password", context.getPassword());
info.putAll(context.getProperties());
String jdbcUrl = "jdbc:mysql://" + context.getUrl() + "/" + context.getSchema();
return DriverManager.getConnection(jdbcUrl, info);
}

View File

@ -1,5 +1,6 @@
package com.databasir.core.infrastructure.connection;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.sql.Connection;
@ -8,6 +9,7 @@ import java.sql.SQLException;
import java.util.Properties;
@Component
@Order(2)
public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFactory {
@Override
@ -16,11 +18,7 @@ public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFa
}
@Override
public Connection getConnection(String username,
String password,
String url,
String schema,
Properties properties) throws SQLException {
public Connection getConnection(Context context) throws SQLException {
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
@ -28,10 +26,10 @@ public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFa
}
Properties info = new Properties();
info.put("user", username);
info.put("password", password);
info.putAll(properties);
String jdbcUrl = "jdbc:postgresql://" + url + "/" + schema;
info.put("user", context.getUsername());
info.put("password", context.getPassword());
info.putAll(context.getProperties());
String jdbcUrl = "jdbc:postgresql://" + context.getUrl() + "/" + context.getSchema();
return DriverManager.getConnection(jdbcUrl, info);
}
}

View File

@ -0,0 +1,84 @@
package com.databasir.core.infrastructure.driver;
import com.databasir.core.domain.DomainErrors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@Component
@Slf4j
@RequiredArgsConstructor
public class DriverResources {
@Value("${databasir.db.driver-directory}")
private String driverBaseDirectory;
private final RestTemplate restTemplate;
public File download(String databaseType, String driverFileUrl) throws IOException {
// create parent directory
if (Files.notExists(Path.of(driverBaseDirectory))) {
Files.createDirectory(Path.of(driverBaseDirectory));
}
String filePath = driverPath(databaseType);
Path path = Path.of(filePath);
if (Files.exists(path)) {
// ignore
log.debug("{} already exists, ignore download from {}", filePath, driverFileUrl);
return path.toFile();
} else {
// download
try {
return restTemplate.execute(driverFileUrl, HttpMethod.GET, null, response -> {
if (response.getStatusCode().is2xxSuccessful()) {
File file = path.toFile();
StreamUtils.copy(response.getBody(), new FileOutputStream(file));
log.info("{} download success ", filePath);
return file;
} else {
log.error("{} download error from {}: {} ", filePath, driverFileUrl, response);
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception("驱动下载失败:"
+ response.getStatusCode()
+ ", "
+ response.getStatusText());
}
});
} catch (IllegalArgumentException e) {
log.error(filePath + " download driver error", e);
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
}
}
}
public void delete(String databaseType) {
Path path = Paths.get(driverPath(databaseType));
try {
Files.deleteIfExists(path);
} catch (IOException e) {
log.error("delete driver error " + databaseType, e);
}
}
private String driverPath(String databaseType) {
String fileName = databaseType + ".jar";
String filePath;
if (driverBaseDirectory.endsWith(File.separator)) {
filePath = driverBaseDirectory + fileName;
} else {
filePath = driverBaseDirectory + File.separator + fileName;
}
return filePath;
}
}

View File

@ -1,5 +0,0 @@
package com.databasir.core.infrastructure.meta;
public class DatabaseMetaResolver {
}

View File

@ -7,6 +7,7 @@ package com.databasir.dao;
import com.databasir.dao.tables.DataSource;
import com.databasir.dao.tables.DataSourceProperty;
import com.databasir.dao.tables.DatabaseDocument;
import com.databasir.dao.tables.DatabaseType;
import com.databasir.dao.tables.DocumentRemark;
import com.databasir.dao.tables.Group;
import com.databasir.dao.tables.Login;
@ -60,6 +61,11 @@ public class Databasir extends SchemaImpl {
*/
public final DatabaseDocument DATABASE_DOCUMENT = DatabaseDocument.DATABASE_DOCUMENT;
/**
* customer database types
*/
public final DatabaseType DATABASE_TYPE = DatabaseType.DATABASE_TYPE;
/**
* The table <code>databasir.document_remark</code>.
*/
@ -159,6 +165,7 @@ public class Databasir extends SchemaImpl {
DataSource.DATA_SOURCE,
DataSourceProperty.DATA_SOURCE_PROPERTY,
DatabaseDocument.DATABASE_DOCUMENT,
DatabaseType.DATABASE_TYPE,
DocumentRemark.DOCUMENT_REMARK,
Group.GROUP,
Login.LOGIN,

View File

@ -7,6 +7,7 @@ package com.databasir.dao;
import com.databasir.dao.tables.DataSource;
import com.databasir.dao.tables.DataSourceProperty;
import com.databasir.dao.tables.DatabaseDocument;
import com.databasir.dao.tables.DatabaseType;
import com.databasir.dao.tables.DocumentRemark;
import com.databasir.dao.tables.Group;
import com.databasir.dao.tables.Login;
@ -26,6 +27,7 @@ import com.databasir.dao.tables.UserRole;
import com.databasir.dao.tables.records.DataSourcePropertyRecord;
import com.databasir.dao.tables.records.DataSourceRecord;
import com.databasir.dao.tables.records.DatabaseDocumentRecord;
import com.databasir.dao.tables.records.DatabaseTypeRecord;
import com.databasir.dao.tables.records.DocumentRemarkRecord;
import com.databasir.dao.tables.records.GroupRecord;
import com.databasir.dao.tables.records.LoginRecord;
@ -64,6 +66,8 @@ public class Keys {
public static final UniqueKey<DataSourceRecord> KEY_DATA_SOURCE_UK_PROJECT_ID = Internal.createUniqueKey(DataSource.DATA_SOURCE, DSL.name("KEY_data_source_uk_project_id"), new TableField[] { DataSource.DATA_SOURCE.PROJECT_ID }, true);
public static final UniqueKey<DataSourcePropertyRecord> KEY_DATA_SOURCE_PROPERTY_PRIMARY = Internal.createUniqueKey(DataSourceProperty.DATA_SOURCE_PROPERTY, DSL.name("KEY_data_source_property_PRIMARY"), new TableField[] { DataSourceProperty.DATA_SOURCE_PROPERTY.ID }, true);
public static final UniqueKey<DatabaseDocumentRecord> KEY_DATABASE_DOCUMENT_PRIMARY = Internal.createUniqueKey(DatabaseDocument.DATABASE_DOCUMENT, DSL.name("KEY_database_document_PRIMARY"), new TableField[] { DatabaseDocument.DATABASE_DOCUMENT.ID }, true);
public static final UniqueKey<DatabaseTypeRecord> KEY_DATABASE_TYPE_PRIMARY = Internal.createUniqueKey(DatabaseType.DATABASE_TYPE, DSL.name("KEY_database_type_PRIMARY"), new TableField[] { DatabaseType.DATABASE_TYPE.ID }, true);
public static final UniqueKey<DatabaseTypeRecord> KEY_DATABASE_TYPE_UK_DATABASE_TYPE_DELETED_DELETED_TOKEN = Internal.createUniqueKey(DatabaseType.DATABASE_TYPE, DSL.name("KEY_database_type_uk_database_type_deleted_deleted_token"), new TableField[] { DatabaseType.DATABASE_TYPE.DATABASE_TYPE_, DatabaseType.DATABASE_TYPE.DELETED, DatabaseType.DATABASE_TYPE.DELETED_TOKEN }, true);
public static final UniqueKey<DocumentRemarkRecord> KEY_DOCUMENT_REMARK_PRIMARY = Internal.createUniqueKey(DocumentRemark.DOCUMENT_REMARK, DSL.name("KEY_document_remark_PRIMARY"), new TableField[] { DocumentRemark.DOCUMENT_REMARK.ID }, true);
public static final UniqueKey<GroupRecord> KEY_GROUP_PRIMARY = Internal.createUniqueKey(Group.GROUP, DSL.name("KEY_group_PRIMARY"), new TableField[] { Group.GROUP.ID }, true);
public static final UniqueKey<LoginRecord> KEY_LOGIN_PRIMARY = Internal.createUniqueKey(Login.LOGIN, DSL.name("KEY_login_PRIMARY"), new TableField[] { Login.LOGIN.ID }, true);

View File

@ -7,6 +7,7 @@ package com.databasir.dao;
import com.databasir.dao.tables.DataSource;
import com.databasir.dao.tables.DataSourceProperty;
import com.databasir.dao.tables.DatabaseDocument;
import com.databasir.dao.tables.DatabaseType;
import com.databasir.dao.tables.DocumentRemark;
import com.databasir.dao.tables.Group;
import com.databasir.dao.tables.Login;
@ -46,6 +47,11 @@ public class Tables {
*/
public static final DatabaseDocument DATABASE_DOCUMENT = DatabaseDocument.DATABASE_DOCUMENT;
/**
* customer database types
*/
public static final DatabaseType DATABASE_TYPE = DatabaseType.DATABASE_TYPE;
/**
* The table <code>databasir.document_remark</code>.
*/

View File

@ -0,0 +1,200 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables;
import com.databasir.dao.Databasir;
import com.databasir.dao.Keys;
import com.databasir.dao.tables.records.DatabaseTypeRecord;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.Row12;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableOptions;
import org.jooq.UniqueKey;
import org.jooq.impl.DSL;
import org.jooq.impl.SQLDataType;
import org.jooq.impl.TableImpl;
/**
* customer database types
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class DatabaseType extends TableImpl<DatabaseTypeRecord> {
private static final long serialVersionUID = 1L;
/**
* The reference instance of <code>databasir.database_type</code>
*/
public static final DatabaseType DATABASE_TYPE = new DatabaseType();
/**
* The class holding records for this type
*/
@Override
public Class<DatabaseTypeRecord> getRecordType() {
return DatabaseTypeRecord.class;
}
/**
* The column <code>databasir.database_type.id</code>.
*/
public final TableField<DatabaseTypeRecord, Integer> ID = createField(DSL.name("id"), SQLDataType.INTEGER.nullable(false).identity(true), this, "");
/**
* The column <code>databasir.database_type.database_type</code>. such as
* mysql, postgresql, mysql5.5 and so on
*/
public final TableField<DatabaseTypeRecord, String> DATABASE_TYPE_ = createField(DSL.name("database_type"), SQLDataType.VARCHAR(128).nullable(false), this, "such as mysql, postgresql, mysql5.5 and so on");
/**
* The column <code>databasir.database_type.icon</code>.
*/
public final TableField<DatabaseTypeRecord, String> ICON = createField(DSL.name("icon"), SQLDataType.VARCHAR(512).nullable(false).defaultValue(DSL.inline("", SQLDataType.VARCHAR)), this, "");
/**
* The column <code>databasir.database_type.description</code>.
*/
public final TableField<DatabaseTypeRecord, String> DESCRIPTION = createField(DSL.name("description"), SQLDataType.VARCHAR(512).nullable(false), this, "");
/**
* The column <code>databasir.database_type.jdbc_driver_file_url</code>.
*/
public final TableField<DatabaseTypeRecord, String> JDBC_DRIVER_FILE_URL = createField(DSL.name("jdbc_driver_file_url"), SQLDataType.VARCHAR(1024).nullable(false), this, "");
/**
* The column <code>databasir.database_type.jdbc_driver_class_name</code>.
*/
public final TableField<DatabaseTypeRecord, String> JDBC_DRIVER_CLASS_NAME = createField(DSL.name("jdbc_driver_class_name"), SQLDataType.VARCHAR(255).nullable(false), this, "");
/**
* The column <code>databasir.database_type.jdbc_protocol</code>.
*/
public final TableField<DatabaseTypeRecord, String> JDBC_PROTOCOL = createField(DSL.name("jdbc_protocol"), SQLDataType.VARCHAR(128).nullable(false), this, "");
/**
* The column <code>databasir.database_type.url_pattern</code>.
*/
public final TableField<DatabaseTypeRecord, String> URL_PATTERN = createField(DSL.name("url_pattern"), SQLDataType.VARCHAR(255).nullable(false), this, "");
/**
* The column <code>databasir.database_type.deleted</code>.
*/
public final TableField<DatabaseTypeRecord, Boolean> DELETED = createField(DSL.name("deleted"), SQLDataType.BOOLEAN.nullable(false).defaultValue(DSL.inline("0", SQLDataType.BOOLEAN)), this, "");
/**
* The column <code>databasir.database_type.deleted_token</code>.
*/
public final TableField<DatabaseTypeRecord, Integer> DELETED_TOKEN = createField(DSL.name("deleted_token"), SQLDataType.INTEGER.nullable(false).defaultValue(DSL.inline("0", SQLDataType.INTEGER)), this, "");
/**
* The column <code>databasir.database_type.update_at</code>.
*/
public final TableField<DatabaseTypeRecord, LocalDateTime> UPDATE_AT = createField(DSL.name("update_at"), SQLDataType.LOCALDATETIME(0).nullable(false).defaultValue(DSL.field("CURRENT_TIMESTAMP", SQLDataType.LOCALDATETIME)), this, "");
/**
* The column <code>databasir.database_type.create_at</code>.
*/
public final TableField<DatabaseTypeRecord, LocalDateTime> CREATE_AT = createField(DSL.name("create_at"), SQLDataType.LOCALDATETIME(0).nullable(false).defaultValue(DSL.field("CURRENT_TIMESTAMP", SQLDataType.LOCALDATETIME)), this, "");
private DatabaseType(Name alias, Table<DatabaseTypeRecord> aliased) {
this(alias, aliased, null);
}
private DatabaseType(Name alias, Table<DatabaseTypeRecord> aliased, Field<?>[] parameters) {
super(alias, null, aliased, parameters, DSL.comment("customer database types"), TableOptions.table());
}
/**
* Create an aliased <code>databasir.database_type</code> table reference
*/
public DatabaseType(String alias) {
this(DSL.name(alias), DATABASE_TYPE);
}
/**
* Create an aliased <code>databasir.database_type</code> table reference
*/
public DatabaseType(Name alias) {
this(alias, DATABASE_TYPE);
}
/**
* Create a <code>databasir.database_type</code> table reference
*/
public DatabaseType() {
this(DSL.name("database_type"), null);
}
public <O extends Record> DatabaseType(Table<O> child, ForeignKey<O, DatabaseTypeRecord> key) {
super(child, key, DATABASE_TYPE);
}
@Override
public Schema getSchema() {
return aliased() ? null : Databasir.DATABASIR;
}
@Override
public Identity<DatabaseTypeRecord, Integer> getIdentity() {
return (Identity<DatabaseTypeRecord, Integer>) super.getIdentity();
}
@Override
public UniqueKey<DatabaseTypeRecord> getPrimaryKey() {
return Keys.KEY_DATABASE_TYPE_PRIMARY;
}
@Override
public List<UniqueKey<DatabaseTypeRecord>> getUniqueKeys() {
return Arrays.asList(Keys.KEY_DATABASE_TYPE_UK_DATABASE_TYPE_DELETED_DELETED_TOKEN);
}
@Override
public DatabaseType as(String alias) {
return new DatabaseType(DSL.name(alias), this);
}
@Override
public DatabaseType as(Name alias) {
return new DatabaseType(alias, this);
}
/**
* Rename this table
*/
@Override
public DatabaseType rename(String name) {
return new DatabaseType(DSL.name(name), null);
}
/**
* Rename this table
*/
@Override
public DatabaseType rename(Name name) {
return new DatabaseType(name, null);
}
// -------------------------------------------------------------------------
// Row12 type methods
// -------------------------------------------------------------------------
@Override
public Row12<Integer, String, String, String, String, String, String, String, Boolean, Integer, LocalDateTime, LocalDateTime> fieldsRow() {
return (Row12) super.fieldsRow();
}
}

View File

@ -0,0 +1,267 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables.pojos;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* customer database types
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class DatabaseTypePojo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String databaseType;
private String icon;
private String description;
private String jdbcDriverFileUrl;
private String jdbcDriverClassName;
private String jdbcProtocol;
private String urlPattern;
private Boolean deleted;
private Integer deletedToken;
private LocalDateTime updateAt;
private LocalDateTime createAt;
public DatabaseTypePojo() {}
public DatabaseTypePojo(DatabaseTypePojo value) {
this.id = value.id;
this.databaseType = value.databaseType;
this.icon = value.icon;
this.description = value.description;
this.jdbcDriverFileUrl = value.jdbcDriverFileUrl;
this.jdbcDriverClassName = value.jdbcDriverClassName;
this.jdbcProtocol = value.jdbcProtocol;
this.urlPattern = value.urlPattern;
this.deleted = value.deleted;
this.deletedToken = value.deletedToken;
this.updateAt = value.updateAt;
this.createAt = value.createAt;
}
public DatabaseTypePojo(
Integer id,
String databaseType,
String icon,
String description,
String jdbcDriverFileUrl,
String jdbcDriverClassName,
String jdbcProtocol,
String urlPattern,
Boolean deleted,
Integer deletedToken,
LocalDateTime updateAt,
LocalDateTime createAt
) {
this.id = id;
this.databaseType = databaseType;
this.icon = icon;
this.description = description;
this.jdbcDriverFileUrl = jdbcDriverFileUrl;
this.jdbcDriverClassName = jdbcDriverClassName;
this.jdbcProtocol = jdbcProtocol;
this.urlPattern = urlPattern;
this.deleted = deleted;
this.deletedToken = deletedToken;
this.updateAt = updateAt;
this.createAt = createAt;
}
/**
* Getter for <code>databasir.database_type.id</code>.
*/
public Integer getId() {
return this.id;
}
/**
* Setter for <code>databasir.database_type.id</code>.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Getter for <code>databasir.database_type.database_type</code>. such as
* mysql, postgresql, mysql5.5 and so on
*/
public String getDatabaseType() {
return this.databaseType;
}
/**
* Setter for <code>databasir.database_type.database_type</code>. such as
* mysql, postgresql, mysql5.5 and so on
*/
public void setDatabaseType(String databaseType) {
this.databaseType = databaseType;
}
/**
* Getter for <code>databasir.database_type.icon</code>.
*/
public String getIcon() {
return this.icon;
}
/**
* Setter for <code>databasir.database_type.icon</code>.
*/
public void setIcon(String icon) {
this.icon = icon;
}
/**
* Getter for <code>databasir.database_type.description</code>.
*/
public String getDescription() {
return this.description;
}
/**
* Setter for <code>databasir.database_type.description</code>.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Getter for <code>databasir.database_type.jdbc_driver_file_url</code>.
*/
public String getJdbcDriverFileUrl() {
return this.jdbcDriverFileUrl;
}
/**
* Setter for <code>databasir.database_type.jdbc_driver_file_url</code>.
*/
public void setJdbcDriverFileUrl(String jdbcDriverFileUrl) {
this.jdbcDriverFileUrl = jdbcDriverFileUrl;
}
/**
* Getter for <code>databasir.database_type.jdbc_driver_class_name</code>.
*/
public String getJdbcDriverClassName() {
return this.jdbcDriverClassName;
}
/**
* Setter for <code>databasir.database_type.jdbc_driver_class_name</code>.
*/
public void setJdbcDriverClassName(String jdbcDriverClassName) {
this.jdbcDriverClassName = jdbcDriverClassName;
}
/**
* Getter for <code>databasir.database_type.jdbc_protocol</code>.
*/
public String getJdbcProtocol() {
return this.jdbcProtocol;
}
/**
* Setter for <code>databasir.database_type.jdbc_protocol</code>.
*/
public void setJdbcProtocol(String jdbcProtocol) {
this.jdbcProtocol = jdbcProtocol;
}
/**
* Getter for <code>databasir.database_type.url_pattern</code>.
*/
public String getUrlPattern() {
return this.urlPattern;
}
/**
* Setter for <code>databasir.database_type.url_pattern</code>.
*/
public void setUrlPattern(String urlPattern) {
this.urlPattern = urlPattern;
}
/**
* Getter for <code>databasir.database_type.deleted</code>.
*/
public Boolean getDeleted() {
return this.deleted;
}
/**
* Setter for <code>databasir.database_type.deleted</code>.
*/
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
/**
* Getter for <code>databasir.database_type.deleted_token</code>.
*/
public Integer getDeletedToken() {
return this.deletedToken;
}
/**
* Setter for <code>databasir.database_type.deleted_token</code>.
*/
public void setDeletedToken(Integer deletedToken) {
this.deletedToken = deletedToken;
}
/**
* Getter for <code>databasir.database_type.update_at</code>.
*/
public LocalDateTime getUpdateAt() {
return this.updateAt;
}
/**
* Setter for <code>databasir.database_type.update_at</code>.
*/
public void setUpdateAt(LocalDateTime updateAt) {
this.updateAt = updateAt;
}
/**
* Getter for <code>databasir.database_type.create_at</code>.
*/
public LocalDateTime getCreateAt() {
return this.createAt;
}
/**
* Setter for <code>databasir.database_type.create_at</code>.
*/
public void setCreateAt(LocalDateTime createAt) {
this.createAt = createAt;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("DatabaseTypePojo (");
sb.append(id);
sb.append(", ").append(databaseType);
sb.append(", ").append(icon);
sb.append(", ").append(description);
sb.append(", ").append(jdbcDriverFileUrl);
sb.append(", ").append(jdbcDriverClassName);
sb.append(", ").append(jdbcProtocol);
sb.append(", ").append(urlPattern);
sb.append(", ").append(deleted);
sb.append(", ").append(deletedToken);
sb.append(", ").append(updateAt);
sb.append(", ").append(createAt);
sb.append(")");
return sb.toString();
}
}

View File

@ -0,0 +1,541 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables.records;
import com.databasir.dao.tables.DatabaseType;
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
import java.time.LocalDateTime;
import org.jooq.Field;
import org.jooq.Record1;
import org.jooq.Record12;
import org.jooq.Row12;
import org.jooq.impl.UpdatableRecordImpl;
/**
* customer database types
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class DatabaseTypeRecord extends UpdatableRecordImpl<DatabaseTypeRecord> implements Record12<Integer, String, String, String, String, String, String, String, Boolean, Integer, LocalDateTime, LocalDateTime> {
private static final long serialVersionUID = 1L;
/**
* Setter for <code>databasir.database_type.id</code>.
*/
public void setId(Integer value) {
set(0, value);
}
/**
* Getter for <code>databasir.database_type.id</code>.
*/
public Integer getId() {
return (Integer) get(0);
}
/**
* Setter for <code>databasir.database_type.database_type</code>. such as
* mysql, postgresql, mysql5.5 and so on
*/
public void setDatabaseType(String value) {
set(1, value);
}
/**
* Getter for <code>databasir.database_type.database_type</code>. such as
* mysql, postgresql, mysql5.5 and so on
*/
public String getDatabaseType() {
return (String) get(1);
}
/**
* Setter for <code>databasir.database_type.icon</code>.
*/
public void setIcon(String value) {
set(2, value);
}
/**
* Getter for <code>databasir.database_type.icon</code>.
*/
public String getIcon() {
return (String) get(2);
}
/**
* Setter for <code>databasir.database_type.description</code>.
*/
public void setDescription(String value) {
set(3, value);
}
/**
* Getter for <code>databasir.database_type.description</code>.
*/
public String getDescription() {
return (String) get(3);
}
/**
* Setter for <code>databasir.database_type.jdbc_driver_file_url</code>.
*/
public void setJdbcDriverFileUrl(String value) {
set(4, value);
}
/**
* Getter for <code>databasir.database_type.jdbc_driver_file_url</code>.
*/
public String getJdbcDriverFileUrl() {
return (String) get(4);
}
/**
* Setter for <code>databasir.database_type.jdbc_driver_class_name</code>.
*/
public void setJdbcDriverClassName(String value) {
set(5, value);
}
/**
* Getter for <code>databasir.database_type.jdbc_driver_class_name</code>.
*/
public String getJdbcDriverClassName() {
return (String) get(5);
}
/**
* Setter for <code>databasir.database_type.jdbc_protocol</code>.
*/
public void setJdbcProtocol(String value) {
set(6, value);
}
/**
* Getter for <code>databasir.database_type.jdbc_protocol</code>.
*/
public String getJdbcProtocol() {
return (String) get(6);
}
/**
* Setter for <code>databasir.database_type.url_pattern</code>.
*/
public void setUrlPattern(String value) {
set(7, value);
}
/**
* Getter for <code>databasir.database_type.url_pattern</code>.
*/
public String getUrlPattern() {
return (String) get(7);
}
/**
* Setter for <code>databasir.database_type.deleted</code>.
*/
public void setDeleted(Boolean value) {
set(8, value);
}
/**
* Getter for <code>databasir.database_type.deleted</code>.
*/
public Boolean getDeleted() {
return (Boolean) get(8);
}
/**
* Setter for <code>databasir.database_type.deleted_token</code>.
*/
public void setDeletedToken(Integer value) {
set(9, value);
}
/**
* Getter for <code>databasir.database_type.deleted_token</code>.
*/
public Integer getDeletedToken() {
return (Integer) get(9);
}
/**
* Setter for <code>databasir.database_type.update_at</code>.
*/
public void setUpdateAt(LocalDateTime value) {
set(10, value);
}
/**
* Getter for <code>databasir.database_type.update_at</code>.
*/
public LocalDateTime getUpdateAt() {
return (LocalDateTime) get(10);
}
/**
* Setter for <code>databasir.database_type.create_at</code>.
*/
public void setCreateAt(LocalDateTime value) {
set(11, value);
}
/**
* Getter for <code>databasir.database_type.create_at</code>.
*/
public LocalDateTime getCreateAt() {
return (LocalDateTime) get(11);
}
// -------------------------------------------------------------------------
// Primary key information
// -------------------------------------------------------------------------
@Override
public Record1<Integer> key() {
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record12 type implementation
// -------------------------------------------------------------------------
@Override
public Row12<Integer, String, String, String, String, String, String, String, Boolean, Integer, LocalDateTime, LocalDateTime> fieldsRow() {
return (Row12) super.fieldsRow();
}
@Override
public Row12<Integer, String, String, String, String, String, String, String, Boolean, Integer, LocalDateTime, LocalDateTime> valuesRow() {
return (Row12) super.valuesRow();
}
@Override
public Field<Integer> field1() {
return DatabaseType.DATABASE_TYPE.ID;
}
@Override
public Field<String> field2() {
return DatabaseType.DATABASE_TYPE.DATABASE_TYPE_;
}
@Override
public Field<String> field3() {
return DatabaseType.DATABASE_TYPE.ICON;
}
@Override
public Field<String> field4() {
return DatabaseType.DATABASE_TYPE.DESCRIPTION;
}
@Override
public Field<String> field5() {
return DatabaseType.DATABASE_TYPE.JDBC_DRIVER_FILE_URL;
}
@Override
public Field<String> field6() {
return DatabaseType.DATABASE_TYPE.JDBC_DRIVER_CLASS_NAME;
}
@Override
public Field<String> field7() {
return DatabaseType.DATABASE_TYPE.JDBC_PROTOCOL;
}
@Override
public Field<String> field8() {
return DatabaseType.DATABASE_TYPE.URL_PATTERN;
}
@Override
public Field<Boolean> field9() {
return DatabaseType.DATABASE_TYPE.DELETED;
}
@Override
public Field<Integer> field10() {
return DatabaseType.DATABASE_TYPE.DELETED_TOKEN;
}
@Override
public Field<LocalDateTime> field11() {
return DatabaseType.DATABASE_TYPE.UPDATE_AT;
}
@Override
public Field<LocalDateTime> field12() {
return DatabaseType.DATABASE_TYPE.CREATE_AT;
}
@Override
public Integer component1() {
return getId();
}
@Override
public String component2() {
return getDatabaseType();
}
@Override
public String component3() {
return getIcon();
}
@Override
public String component4() {
return getDescription();
}
@Override
public String component5() {
return getJdbcDriverFileUrl();
}
@Override
public String component6() {
return getJdbcDriverClassName();
}
@Override
public String component7() {
return getJdbcProtocol();
}
@Override
public String component8() {
return getUrlPattern();
}
@Override
public Boolean component9() {
return getDeleted();
}
@Override
public Integer component10() {
return getDeletedToken();
}
@Override
public LocalDateTime component11() {
return getUpdateAt();
}
@Override
public LocalDateTime component12() {
return getCreateAt();
}
@Override
public Integer value1() {
return getId();
}
@Override
public String value2() {
return getDatabaseType();
}
@Override
public String value3() {
return getIcon();
}
@Override
public String value4() {
return getDescription();
}
@Override
public String value5() {
return getJdbcDriverFileUrl();
}
@Override
public String value6() {
return getJdbcDriverClassName();
}
@Override
public String value7() {
return getJdbcProtocol();
}
@Override
public String value8() {
return getUrlPattern();
}
@Override
public Boolean value9() {
return getDeleted();
}
@Override
public Integer value10() {
return getDeletedToken();
}
@Override
public LocalDateTime value11() {
return getUpdateAt();
}
@Override
public LocalDateTime value12() {
return getCreateAt();
}
@Override
public DatabaseTypeRecord value1(Integer value) {
setId(value);
return this;
}
@Override
public DatabaseTypeRecord value2(String value) {
setDatabaseType(value);
return this;
}
@Override
public DatabaseTypeRecord value3(String value) {
setIcon(value);
return this;
}
@Override
public DatabaseTypeRecord value4(String value) {
setDescription(value);
return this;
}
@Override
public DatabaseTypeRecord value5(String value) {
setJdbcDriverFileUrl(value);
return this;
}
@Override
public DatabaseTypeRecord value6(String value) {
setJdbcDriverClassName(value);
return this;
}
@Override
public DatabaseTypeRecord value7(String value) {
setJdbcProtocol(value);
return this;
}
@Override
public DatabaseTypeRecord value8(String value) {
setUrlPattern(value);
return this;
}
@Override
public DatabaseTypeRecord value9(Boolean value) {
setDeleted(value);
return this;
}
@Override
public DatabaseTypeRecord value10(Integer value) {
setDeletedToken(value);
return this;
}
@Override
public DatabaseTypeRecord value11(LocalDateTime value) {
setUpdateAt(value);
return this;
}
@Override
public DatabaseTypeRecord value12(LocalDateTime value) {
setCreateAt(value);
return this;
}
@Override
public DatabaseTypeRecord values(Integer value1, String value2, String value3, String value4, String value5, String value6, String value7, String value8, Boolean value9, Integer value10, LocalDateTime value11, LocalDateTime value12) {
value1(value1);
value2(value2);
value3(value3);
value4(value4);
value5(value5);
value6(value6);
value7(value7);
value8(value8);
value9(value9);
value10(value10);
value11(value11);
value12(value12);
return this;
}
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
/**
* Create a detached DatabaseTypeRecord
*/
public DatabaseTypeRecord() {
super(DatabaseType.DATABASE_TYPE);
}
/**
* Create a detached, initialised DatabaseTypeRecord
*/
public DatabaseTypeRecord(Integer id, String databaseType, String icon, String description, String jdbcDriverFileUrl, String jdbcDriverClassName, String jdbcProtocol, String urlPattern, Boolean deleted, Integer deletedToken, LocalDateTime updateAt, LocalDateTime createAt) {
super(DatabaseType.DATABASE_TYPE);
setId(id);
setDatabaseType(databaseType);
setIcon(icon);
setDescription(description);
setJdbcDriverFileUrl(jdbcDriverFileUrl);
setJdbcDriverClassName(jdbcDriverClassName);
setJdbcProtocol(jdbcProtocol);
setUrlPattern(urlPattern);
setDeleted(deleted);
setDeletedToken(deletedToken);
setUpdateAt(updateAt);
setCreateAt(createAt);
}
/**
* Create a detached, initialised DatabaseTypeRecord
*/
public DatabaseTypeRecord(DatabaseTypePojo value) {
super(DatabaseType.DATABASE_TYPE);
if (value != null) {
setId(value.getId());
setDatabaseType(value.getDatabaseType());
setIcon(value.getIcon());
setDescription(value.getDescription());
setJdbcDriverFileUrl(value.getJdbcDriverFileUrl());
setJdbcDriverClassName(value.getJdbcDriverClassName());
setJdbcProtocol(value.getJdbcProtocol());
setUrlPattern(value.getUrlPattern());
setDeleted(value.getDeleted());
setDeletedToken(value.getDeletedToken());
setUpdateAt(value.getUpdateAt());
setCreateAt(value.getCreateAt());
}
}
}

View File

@ -80,6 +80,20 @@ public abstract class BaseDao<R> {
new DataNotExistsException("data not exists in " + table.getName() + " with id = " + id));
}
public Optional<R> selectOptionalOne(Condition condition) {
return getDslContext()
.select(table.fields()).from(table).where(condition)
.fetchOptionalInto(pojoType);
}
public R selectOne(Condition condition) {
return selectOptionalOne(condition)
.orElseThrow(() -> new DataNotExistsException("data not exists in "
+ table.getName()
+ " with condition = "
+ condition));
}
public List<R> selectInIds(List<? extends Serializable> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();

View File

@ -0,0 +1,61 @@
package com.databasir.dao.impl;
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
import lombok.Getter;
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import static com.databasir.dao.Tables.DATABASE_TYPE;
@Repository
public class DatabaseTypeDao extends BaseDao<DatabaseTypePojo> {
@Autowired
@Getter
private DSLContext dslContext;
public DatabaseTypeDao() {
super(DATABASE_TYPE, DatabaseTypePojo.class);
}
public boolean existsByDatabaseType(String databaseType) {
return exists(DATABASE_TYPE.DATABASE_TYPE_.eq(databaseType)
.and(DATABASE_TYPE.DELETED.eq(false)));
}
public boolean existsById(Integer id) {
return exists(DATABASE_TYPE.ID.eq(id)
.and(DATABASE_TYPE.DELETED.eq(false)));
}
public DatabaseTypePojo selectByDatabaseType(String databaseType) {
return this.selectOne(DATABASE_TYPE.DATABASE_TYPE_.eq(databaseType)
.and(DATABASE_TYPE.DELETED.eq(false)));
}
@Override
public List<DatabaseTypePojo> selectAll() {
return this.getDslContext().selectFrom(DATABASE_TYPE)
.where(DATABASE_TYPE.DELETED.eq(false))
.orderBy(DATABASE_TYPE.ID.desc())
.fetchInto(DatabaseTypePojo.class);
}
public int deleteById(Integer id) {
return this.getDslContext()
.update(DATABASE_TYPE)
.set(DATABASE_TYPE.DELETED, true)
.set(DATABASE_TYPE.DELETED_TOKEN, DATABASE_TYPE.ID)
.where(DATABASE_TYPE.ID.eq(id)
.and(DATABASE_TYPE.DELETED.eq(false)))
.execute();
}
public Optional<DatabaseTypePojo> selectOptionalById(Integer id) {
return super.selectOptionalOne(DATABASE_TYPE.DELETED.eq(false).and(DATABASE_TYPE.ID.eq(id)));
}
}

View File

@ -5,6 +5,7 @@ import com.databasir.dao.value.GroupProjectCountPojo;
import lombok.Getter;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
@ -14,6 +15,7 @@ import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@ -100,4 +102,17 @@ public class ProjectDao extends BaseDao<ProjectPojo> {
.where(PROJECT.GROUP_ID.eq(groupId).and(PROJECT.DELETED.eq(false)))
.fetchInto(Integer.class);
}
public Map<String, Integer> countByDatabaseTypes(List<String> databaseTypes) {
if (databaseTypes == null || databaseTypes.isEmpty()) {
return Collections.emptyMap();
}
return getDslContext()
.select(DSL.count(DATA_SOURCE), DATA_SOURCE.DATABASE_TYPE)
.from(DATA_SOURCE)
.innerJoin(PROJECT).on(PROJECT.ID.eq(DATA_SOURCE.PROJECT_ID))
.where(PROJECT.DELETED.eq(false)).and(DATA_SOURCE.DATABASE_TYPE.in(databaseTypes))
.groupBy(DATA_SOURCE.DATABASE_TYPE)
.fetchMap(DATA_SOURCE.DATABASE_TYPE, DSL.count(DATA_SOURCE));
}
}

View File

@ -0,0 +1,23 @@
CREATE TABLE IF NOT EXISTS database_type
(
id INT PRIMARY KEY AUTO_INCREMENT,
database_type VARCHAR(128) NOT NULL COMMENT 'such as mysql, postgresql, mysql5.5 and so on',
icon VARCHAR(512) NOT NULL DEFAULT '',
description VARCHAR(512) NOT NULL,
jdbc_driver_file_url VARCHAR(1024) NOT NULL,
jdbc_driver_class_name VARCHAR(255) NOT NULL,
jdbc_protocol VARCHAR(128) NOT NULL,
url_pattern VARCHAR(255) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
deleted_token INT NOT NULL DEFAULT 0,
update_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
create_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uk_database_type_deleted_deleted_token UNIQUE (database_type, deleted, deleted_token)
) CHARSET utf8mb4
COLLATE utf8mb4_unicode_ci COMMENT 'customer database types';
REPLACE INTO databasir.database_type (id, database_type, icon, DESCRIPTION, jdbc_driver_file_url,
jdbc_driver_class_name,
jdbc_protocol, url_pattern)
VALUES (1, 'mysql', '', 'system default mysql', 'N/A', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql', '{{jdbc.protocol}}://{{db.url}}/{{db.name}}'),
(2, 'postgresql', '', 'system default postgresql', 'N/A', 'org.postgresql.Driver', 'jdbc:postgresql', '{{jdbc.protocol}}://{{db.url}}/{{db.name}}');