feat: 发布0.0.1版本

This commit is contained in:
wangyu 2022-09-07 13:17:25 +08:00
parent 72f74b2b8c
commit e390b81a98
18 changed files with 736 additions and 22 deletions

View File

@ -19,7 +19,7 @@
<dependency>
<artifactId>fluent-sql-core</artifactId>
<groupId>group.flyfish.framework</groupId>
<version>1.0-SNAPSHOT</version>
<version>0.0.1</version>
</dependency>
```

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>fluent-sql</artifactId>
<groupId>group.flyfish.framework</groupId>
<version>1.0-SNAPSHOT</version>
<version>0.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -23,7 +23,7 @@
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>

View File

@ -2,9 +2,9 @@ package group.flyfish.fluent.chain;
import group.flyfish.fluent.chain.common.PreSqlChain;
import group.flyfish.fluent.chain.select.SelectComposite;
import group.flyfish.fluent.operations.FluentSQLOperations;
import group.flyfish.fluent.update.Update;
import group.flyfish.fluent.utils.sql.SFunction;
import org.springframework.jdbc.core.JdbcOperations;
import static group.flyfish.fluent.utils.sql.SqlNameUtils.cast;
@ -54,11 +54,11 @@ public interface SQL {
}
/**
* 绑定数据源上下文基于jdbc template
* 绑定数据源上下文可自由切换实现
*
* @param operations jdbc操作
*/
static void bind(JdbcOperations operations) {
static void bind(FluentSQLOperations operations) {
SQLImpl.bind(operations);
}
}

View File

@ -6,7 +6,8 @@ import group.flyfish.fluent.chain.common.PreSqlChain;
import group.flyfish.fluent.chain.select.AfterOrderSqlChain;
import group.flyfish.fluent.chain.select.AfterWhereSqlChain;
import group.flyfish.fluent.chain.update.AfterSetSqlChain;
import group.flyfish.fluent.mapping.SQLMappedRowMapper;
import group.flyfish.fluent.entity.SQLEntity;
import group.flyfish.fluent.operations.FluentSQLOperations;
import group.flyfish.fluent.query.JoinCandidate;
import group.flyfish.fluent.query.Parameterized;
import group.flyfish.fluent.query.Query;
@ -18,8 +19,6 @@ import group.flyfish.fluent.utils.sql.ConcatSegment;
import group.flyfish.fluent.utils.sql.EntityNameUtils;
import group.flyfish.fluent.utils.sql.SFunction;
import group.flyfish.fluent.utils.sql.SqlNameUtils;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.util.Assert;
import java.util.ArrayList;
@ -35,7 +34,7 @@ import java.util.stream.Collectors;
final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, PreSqlChain, HandleSqlChain, AfterJoinSqlChain, AfterSetSqlChain {
// 共享的操作
private static JdbcOperations SHARED_OPERATIONS;
private static FluentSQLOperations SHARED_OPERATIONS;
// 参数map有序
private final List<Object> parameters = new ArrayList<>();
@ -43,11 +42,11 @@ final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, Pre
private final boolean debug = false;
/**
* 基于jdbc template
* 绑定实现类
*
* @param operations jdbc操作
*/
public static void bind(JdbcOperations operations) {
public static void bind(FluentSQLOperations operations) {
SHARED_OPERATIONS = operations;
}
@ -184,12 +183,7 @@ final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, Pre
* @param <T> 泛型
*/
public <T> T one(Class<T> clazz) {
try {
return SHARED_OPERATIONS.queryForObject(sql().concat(" limit 1"),
new SQLMappedRowMapper<>(clazz), parsedParameters());
} catch (EmptyResultDataAccessException e) {
return null;
}
return SHARED_OPERATIONS.selectOne(entity(), clazz);
}
/**
@ -200,7 +194,7 @@ final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, Pre
*/
@Override
public <T> List<T> list(Class<T> clazz) {
return SHARED_OPERATIONS.query(sql(), new SQLMappedRowMapper<>(clazz), parsedParameters());
return SHARED_OPERATIONS.select(entity(), clazz);
}
/**
@ -210,7 +204,7 @@ final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, Pre
*/
@Override
public int execute() {
return SHARED_OPERATIONS.update(sql(), parsedParameters());
return SHARED_OPERATIONS.execute(entity());
}
/**
@ -252,4 +246,13 @@ final class SQLImpl extends ConcatSegment<SQLImpl> implements SQLOperations, Pre
parameters.addAll(params.getParameters());
return false;
}
/**
* 将本实体转换为sql实体
*
* @return 转换结果
*/
private SQLEntity entity() {
return SQLEntity.of(this::sql, this::parsedParameters);
}
}

View File

@ -0,0 +1,38 @@
package group.flyfish.fluent.entity;
import java.util.function.Supplier;
/**
* sql运行实体
*
* @author wangyu
*/
public class SQLEntity {
private static final Supplier<Object[]> EMPTY_PARAMETERS = () -> new Object[]{};
// sql提供者
private Supplier<String> sqlProvider;
// sql参数表提供者
private Supplier<Object[]> parametersProvider;
public static SQLEntity of(Supplier<String> sqlProvider) {
return of(sqlProvider, EMPTY_PARAMETERS);
}
public static SQLEntity of(Supplier<String> sqlProvider, Supplier<Object[]> parametersProvider) {
SQLEntity entity = new SQLEntity();
entity.sqlProvider = sqlProvider;
entity.parametersProvider = parametersProvider;
return entity;
}
public String getSql() {
return sqlProvider.get();
}
public Object[] getParameters() {
return parametersProvider.get();
}
}

View File

@ -0,0 +1,45 @@
package group.flyfish.fluent.operations;
import group.flyfish.fluent.entity.SQLEntity;
import org.springframework.lang.Nullable;
import java.util.List;
/**
* sql query操作
*
* @author wangyu
*/
public interface FluentSQLOperations {
/**
* 执行一条sql并且序列化为对象
* 注意如果查询不止一条该方法仅返回第一条数据
* 如果没有结果将返回null
*
* @param entity sql实体
* @param clazz 目标类型
* @param <T> 目标泛型
* @return 查询结果
*/
@Nullable
<T> T selectOne(SQLEntity entity, Class<T> clazz);
/**
* 执行一条sql并且查询出所有行
*
* @param entity sql实体
* @param clazz 目标类型
* @param <T> 目标泛型
* @return 返回的列表
*/
<T> List<T> select(SQLEntity entity, Class<T> clazz);
/**
* 直接执行sql根据update count返回更新行数如果是查询永远返回0
*
* @param entity sql实体
* @return 更新行数
*/
int execute(SQLEntity entity);
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>fluent-sql</artifactId>
<groupId>group.flyfish.framework</groupId>
<version>1.0-SNAPSHOT</version>
<version>0.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -16,4 +16,29 @@
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>group.flyfish.framework</groupId>
<artifactId>fluent-sql-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,76 @@
package group.flyfish.fluent.operations;
import group.flyfish.fluent.chain.SQL;
import group.flyfish.fluent.entity.SQLEntity;
import group.flyfish.fluent.mapping.SQLMappedRowMapper;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.util.ClassUtils;
import java.util.List;
/**
* jdbc template实现的查询操作
*
* @author wangyu
*/
public class JdbcTemplateFluentSQLOperations implements FluentSQLOperations {
private final JdbcOperations jdbcOperations;
/**
* 实例化 + 自动绑定
*
* @param operations spring jdbc template
*/
public JdbcTemplateFluentSQLOperations(JdbcOperations operations) {
this.jdbcOperations = operations;
SQL.bind(this);
}
/**
* 执行一条sql并且序列化为对象
* 注意如果查询不止一条该方法仅返回第一条数据
* 如果没有结果将返回null
*
* @param entity sql实体
* @param clazz 目标类型
* @return 查询结果
*/
@Override
@SuppressWarnings("all")
public <T> T selectOne(SQLEntity entity, Class<T> clazz) {
try {
String sql = entity.getSql().concat(" limit 1");
if (ClassUtils.isPrimitiveOrWrapper(clazz)) {
return jdbcOperations.queryForObject(sql, clazz, entity.getParameters());
}
return jdbcOperations.queryForObject(sql, new SQLMappedRowMapper<>(clazz), entity.getParameters());
} catch (EmptyResultDataAccessException e) {
return null;
}
}
/**
* 执行一条sql并且查询出所有行
*
* @param entity sql实体
* @param clazz 目标类型
* @return 返回的列表
*/
@Override
public <T> List<T> select(SQLEntity entity, Class<T> clazz) {
return jdbcOperations.query(entity.getSql(), new SQLMappedRowMapper<>(clazz), entity.getParameters());
}
/**
* 直接执行sql根据update count返回更新行数如果是查询永远返回0
*
* @param entity sql实体
* @return 更新行数
*/
@Override
public int execute(SQLEntity entity) {
return jdbcOperations.update(entity.getSql(), entity.getParameters());
}
}

View File

@ -0,0 +1,77 @@
package group.flyfish.framework;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.mysql.cj.jdbc.Driver;
import group.flyfish.fluent.operations.FluentSQLOperations;
import group.flyfish.fluent.operations.JdbcTemplateFluentSQLOperations;
import group.flyfish.fluent.utils.data.ObjectMappers;
import group.flyfish.framework.entity.SaasOrder;
import group.flyfish.framework.entity.SaasPlan;
import group.flyfish.framework.entity.SaasTenant;
import group.flyfish.framework.vo.TenantContext;
import org.junit.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;
import static group.flyfish.fluent.chain.SQL.select;
import static group.flyfish.fluent.chain.select.SelectComposite.composite;
import static group.flyfish.fluent.query.Query.where;
/**
* 链式jdbc测试
*
* @author wangyu
*/
public class FluentJdbcTest {
/**
* 静态测试demo
* 实际测试请根据自己的数据库字段书写实体
*
* @throws SQLException sql异常
*/
@Test
public void testSql() throws SQLException, JsonProcessingException {
DataSource dataSource = new SimpleDriverDataSource(
new Driver(),
"jdbc:mysql://127.0.0.1:3306/epi_project?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai",
"root",
"oI3WtMO8h%mSYARp"
);
// 基于构造器自动绑定注册在实际应用中使用@Bean声明即可可参考下面的demo
new JdbcTemplateFluentSQLOperations(new JdbcTemplate(dataSource));
// 一个平平无奇的查询
List<TenantContext> list = select(
// 查询租户全量字段
composite(SaasTenant::getId, SaasTenant::getName, SaasTenant::getIdentifier, SaasTenant::getDatasource,
SaasTenant::getStorage, SaasTenant::getStatus, SaasTenant::getEnable),
// 查询套餐
composite(SaasOrder::getQuotaConfig, SaasOrder::getOrderTime, SaasOrder::getExpireTime,
SaasOrder::getOrderType))
.from(SaasTenant.class)
.leftJoin(SaasOrder.class).on(where(SaasOrder::getTenantId).eq(SaasTenant::getId))
.leftJoin(SaasPlan.class).on(where(SaasPlan::getId).eq(SaasOrder::getPlanId))
.matching(where(SaasTenant::getEnable).eq(true))
.list(TenantContext.class);
// 打印效果
System.out.println(ObjectMappers.shared().writeValueAsString(list));
}
/**
* 实际应用中使用bean注入并实例化
*
* @param operations 从spring依赖注入的jdbc template
*/
@Bean
public FluentSQLOperations fluentSQLOperations(JdbcOperations operations) {
return new JdbcTemplateFluentSQLOperations(operations);
}
}

View File

@ -0,0 +1,41 @@
package group.flyfish.framework.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* 所有实体类继承
*/
@Getter
@Setter
public abstract class Po implements Serializable {
@Id
@Property("主键")
private String id;
@Column(name = "create_by")
@Property("创建者")
private String createBy;
@Column(name = "create_time")
@Property("创建时间")
private Date createTime;
@Column(name = "update_by")
@Property("更新者")
private String updateBy;
@Column(name = "update_time")
@Property("更新时间")
private Date updateTime;
@Column(name = "is_delete")
@Property("逻辑删除标志")
private Boolean delete;
}

View File

@ -0,0 +1,24 @@
package group.flyfish.framework.entity;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Property {
/**
* @return 属性名称
*/
String value();
/**
* @return 属性描述
*/
String description() default "";
/**
* @return 是否唯一
*/
boolean unique() default false;
}

View File

@ -0,0 +1,79 @@
package group.flyfish.framework.entity;
import group.flyfish.fluent.binding.JSONInject;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.util.Date;
/**
* 租户订阅表
*
* @author wangyu
*/
@Table(name = "saas_order")
@Getter
@Setter
public class SaasOrder extends Po {
@Property("订阅备注")
private String comment;
@Property("套餐id")
@ManyToOne
@Column(name = "plan_id")
private String planId;
@Property("租户id")
@ManyToOne
@Column(name = "tenant_id")
private String tenantId;
@Property("配额配置JSON")
@Column(name = "quota_config")
@JSONInject
private SaasQuota quotaConfig;
@Property("订阅类型 LIMITED:有限期订阅,UNLIMITED:无限期订阅)")
@Column(name = "order_type")
private Type orderType;
@Property("订阅时间")
@Column(name = "order_time")
private Date orderTime;
@Property("过期时间")
@Column(name = "expire_time")
private Date expireTime;
@Property("订阅状态 VALID:有效,INVALID:无效,ERROR:异常)")
@Column(name = "status")
private Status status;
@Getter
@AllArgsConstructor
public enum Status {
VALID("有效"),
INVALID("无效"),
ERROR("异常");
private final String name;
}
@Getter
@AllArgsConstructor
public enum Type {
LIMITED("有限期订阅"),
UNLIMITED("无限期订阅");
private final String name;
}
}

View File

@ -0,0 +1,40 @@
package group.flyfish.framework.entity;
import group.flyfish.fluent.binding.JSONInject;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Table;
/**
* saas计划套餐
*
* @author wangyu
*/
@Table(name = "saas_plan")
@Getter
@Setter
public class SaasPlan extends Po {
@Property("套餐名称")
@Column(name = "name")
private String name;
@Property("套餐描述")
@Column(name = "description")
private String description;
@Property("配额配置JSON")
@Column(name = "quota_config")
@JSONInject
private SaasQuota quotaConfig;
@Property("启用状态(未启用0,已启用1)")
@Column(name = "enable")
private Boolean enable;
@Property("套餐状态 NORMAL:上架中,DISABLED:已下架)")
@Column(name = "status")
private String status;
}

View File

@ -0,0 +1,54 @@
package group.flyfish.framework.entity;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* saas配额属性
*
* @author wangyu
*/
@Getter
@Setter
public class SaasQuota implements Serializable {
private static final long serialVersionUID = -3615943142615938771L;
// 用户限额
@Property("在线用户数限制")
private Integer userOnlineLimit;
// mysql 运行限额
@Property("每小时最大查询")
private Integer databaseMaxQueriesPerHour;
@Property("每小时最大修改")
private Integer databaseMaxUpdatesPerHour;
@Property("每小时最大连接数")
private Integer databaseMaxConnectionsPerHour;
@Property("当前用户最大连接数")
private Integer databaseMaxUserConnections;
// mysql 存储限额
@Property("单库最大存储量(byte)")
private Long databaseMaxSize;
// 文件存储限额
@Property("文件最大存储量(byte)")
private Long storageMaxSize;
@Property("上行速率最大值(KB/s)")
private Long storageUpLinkMaxSpeed;
@Property("下行速率最大值(KB/s)")
private Long storageDownLinkMaxSpeed;
// 内存数据库配额限制
@Property("最大存储键值对数`")
private Long cacheMaxKeys;
// 应用短信收费api等
@Property("短信最大发送条数")
private Integer smsMaxCount;
@Property("实名认证最大次数")
private Integer verifyMaxCount;
}

View File

@ -0,0 +1,120 @@
package group.flyfish.framework.entity;
import group.flyfish.fluent.binding.JSONInject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Map;
/**
* saas租户
*
* @author wangyu
*/
@Getter
@Setter
@Table(name = "saas_tenant")
public class SaasTenant extends Po {
@Property("租户名称")
private String name;
@Property(value = "租户标识", description = "系统唯一标识", unique = true)
private String identifier;
@Property(value = "租户代码", description = "统一社会信用代码")
private String code;
@Property(value = "数据库配置", description = "租户自有数据库配置")
@JSONInject
private DataSourceConfig datasource;
@Property(value = "存储配置", description = "租户自有存储配置")
@JSONInject
private StorageConfig storage;
@Property("租户状态")
private Status status;
@Property("合同状态")
private ContractStatus contractStatus;
@Property("是否启用")
private Boolean enable;
@Property("备注")
private String comment;
@Getter
@AllArgsConstructor
public enum Status {
PENDING("未开通"),
TRYING("试用中"),
CREATED("已开通"),
EXPIRED("已过期"),
CANCELED("已注销");
private final String name;
}
@Getter
@AllArgsConstructor
public enum ContractStatus {
PENDING("未签订"),
ENGAGED("已签订"),
ABANDONED("已作废");
private final String name;
}
/**
* 租户数据源配置信息
*
* @author wangyu
*/
@Data
public static class DataSourceConfig implements Serializable {
private static final long serialVersionUID = 3751414771731042514L;
@Property("连接字符串")
private String connection;
@Property("驱动名称")
private String driverClass = "com.mysql.cj.jdbc.Driver";
@Property("用户名")
private String username;
@Property("密码")
private String password;
}
/**
* 租户存储信息
*/
@Data
public static class StorageConfig implements Serializable {
private static final long serialVersionUID = -9032829515869208750L;
//minio用户信息
@Property(value = "服务器地址", description = "可以是sftp服务器地址、minio地址、azure地址")
private String server;
@Property(value = "目录名", description = "可以是本地目录、sftp目录、minio桶名称azure桶名称")
private String directory;
@Property(value = "用户名", description = "可以是sftp用户名、minio用户名、azure用户名")
private String username;
@Property(value = "用户密码", description = "可以是sftp摩玛、minio密码、azure密码等")
private String password;
@Property("其他连接参数。根据不同的文件存储方式可以自由放入")
private Map<String, Object> properties;
}
}

View File

@ -0,0 +1,65 @@
package group.flyfish.framework.vo;
import group.flyfish.fluent.binding.Alias;
import group.flyfish.fluent.binding.JSONInject;
import group.flyfish.framework.entity.SaasOrder;
import group.flyfish.framework.entity.SaasQuota;
import group.flyfish.framework.entity.SaasTenant;
import lombok.Data;
import javax.persistence.Column;
import java.io.Serializable;
import java.util.Date;
/**
* 租户上下文
*
* @author wangyu
* 负责租户生命周期管理缓存读写驻留在请求上下文中
*/
@Data
public class TenantContext implements Serializable {
private static final long serialVersionUID = -6912908497223962047L;
// 租户id
private String id;
// 租户名称
private String name;
// 租户标识符
private String identifier;
// 租户数据源配置
@JSONInject
private SaasTenant.DataSourceConfig datasource;
// 租户存储配置
@JSONInject
private SaasTenant.StorageConfig storage;
// 租户状态
private SaasTenant.Status status;
// 租户启用状态
private Boolean enable;
// 配额信息
@Alias("quota_config")
@JSONInject
private SaasQuota quota;
// 订阅类型 LIMITED:有限期订阅,UNLIMITED:无限期订阅
@Column(name = "order_type")
private SaasOrder.Type orderType;
// 订阅时间
@Column(name = "order_time")
private Date orderTime;
// 过期时间
@Column(name = "expire_time")
private Date expireTime;
}

29
pom.xml
View File

@ -7,7 +7,7 @@
<groupId>group.flyfish.framework</groupId>
<artifactId>fluent-sql</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<version>0.0.1</version>
<modules>
<module>fluent-sql-core</module>
<module>fluent-sql-jdbctemplate</module>
@ -59,6 +59,11 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group.flyfish.framework</groupId>
<artifactId>fluent-sql-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@ -69,6 +74,16 @@
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@ -79,6 +94,18 @@
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>