Code Monkey home page Code Monkey logo

sqlex's Introduction

logo

GitHub Workflow Status GitHub issues Maven Central Document LICENSE

SqlEx 是什么

SqlEx (SQL extension) 是一个简单的 DB helper.
从实际应用角度出发, 解决编程语言(Java)和关系型数据库之间对于类型和结构认知不匹配的问题.
主要思路是通过对数据库结构和 SQL 做语义分析, 依据分析得出的结果, 生成对应的结果类型. 提供强类型安全的编程体验.
将大部分错误从运行时前推到编译时/从编译时前推到编辑时, 保证错误写法有提示, 错误写法无法编译通过, 能编译通过进运行环境的程序不会出现数据库结构/类型错误.

特性一览

  • 自带数据库版本管理(类似 flyway)
  • 提供sqlm语言编写 SQL, 能自动生成结果类
  • 根据数据库结构自动生成 Fluent API
  • 提供 IDEA 插件, 提升开发体验
  • 与 SpringBoot 良好集成

SqlEx Method 语言

sqlm是另一种"写 Java"的方式, 专用于编写复杂的数据库访问方法. 能自动分析 SQL 并生成对应的结果类型.

动画演示(加载有点慢/直接打开):

image

Fluent API

SqlEx 会根据数据库信息, 准备好对应的表操作对象(无须自己手动定义实体), 提供 Fluent API 来对数据库做简单操作.

动画演示(加载有点慢/直接打开):

fluent api

更多

详细文档请访问 SqlEx 文档

关于

本项目中 MySQL 相关的语法/逻辑计划分析来源于 TiDB 项目

另外部分代码的实现上参考了如下项目:

再次特别感谢上述项目的开发者对开源事业做出的贡献.

sqlex's People

Contributors

badkid90s avatar raintean avatar wjy-jy avatar xpress-d avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

sqlex's Issues

类ORM设计

类 ORM 设计

根据 Repository 中 Schema 的定义, 针对每一个表, 生成实体对象(Entity)表操作对象(AccessObject).

假定 schema 定义

如有表定义

create table person(
    id integer auto_increment primary key,
    name varchar(255) not null,
    age integer not null
)

表的实体对象

依据 SqlEx 中标准的数据映射, 根据表的字段生成实体类的属性.

则对应的实体类Person

// 实体类,POJO
class Person {
    Integer id;
    String name;
    Integer age;
}

表的操作对象

根据对表信息的分析, 生成如下操作对象

class PersonTable extends TableInsert<Person>{
    //字段表达式(代表了表中的字段)
    static ColumnExpression id;
    static ColumnExpression name;
    static ColumnExpression age;

    static class Update extends TableUpdate<Update> {
        //值更新函数
        T setId(Integer id);
        T setName(String name);
        T setAge(Integer age);
    }

    //更新
    Update update();

    //删除
    TableDelete delete();

    //查找
    TableQuery<Person> select();
}

// 以下类包含在core模块中
class TableInsert<T> {
    //新建行(插入),返回插入后的实体对象(包含自动填充字段的值)
    T save(T person);
    //如果key重复,则执行更新
    T upsert(T person);
}

class TableUpdate<T> extends WhereBuilder<T> {
    //执行更新,返回更新的行数
    long execute();
}

class TableDelete extends WhereBuilder<TableDelete> {
    //执行删除,返回删除的行数
    long execute();
}

class TableQuery<T> extends WhereBuilder<TableQuery<T>> {
    //排序
    TableQuery<T> order(Expression exp);
    TableQuery<T> order(Expression exp, Order order);

    //limit
    //跳过多少个
    TableQuery<T> skip(long number);
    //取值多少个
    TableQuery<T> take(long number);

    //加锁
    TableQuery<T> forUpdate();

    //统计行数
    long count();
    //查找
    List<T> find();
    //查找单个(limit 1)
    T findOne() {
        List<T> results =  this.take(1).find();
        if(results.size>0)
            return results.get(0);
        return null;
    }
    //分页
    PagedResult<T> page(long pageSize,long pageNo) {
        long total = this.count();
        List<T> data = this.find();
        return new PagedResult(pageSize,pageNo,total,data);
    }
}

class WhereBuilder<T> {
    //条件构造函数
    T where(Expression exp);
    T where(()->Expression);
}

有了如上的表操作对象, 则可以通过 API 的方式构造查询, 如

//从DaoFactory中获取表操作对象的实例
personTable = daoFactory.getTableInstance(PersonTable.class);

// select * from where age > 10
personTable.select().where(PersonTable.age.gt(arg(10))).find();

// select * from where age > 10 and name like '%ABC'
personTable.select()
    .where(
            PersonTable.age.gt(arg(10))
                .and(PersonTabe.name.like(arg("%ABC")))
            )
    .find();
personTable.select()
    .where(PersonTable.age.gt(arg(10)))
    .where(PersonTabe.name.like(arg("%ABC")))
    .find();
personTable.select()
    .where(()->{
        Expression exp = arg(true);
        exp = exp.and(PersonTable.age.gt(arg(10)));
        exp = exp.and(PersonTabe.name.like(arg("%ABC")));
        return exp;
    })
    .find();
//kotlin
personTable.select()
    .where {
       age > 10 and name like "%ABC"
    }
    .find();

// select * from person where age > 10 order by name limit 10, 1
personTable.select()
    .where(PersonTable.age.gt(arg(10)))
    .order(PersonTable.name)
    .skip(10).take(1)
    .find();

// update person set name = 'test' where id = 1;
personTable.update()
    .setName("test")
    .where(PersonTable.id.eq(arg(1)))
    .execute();

// delete from person where name like('%ABC')
personTable.delete().where(PersonTable.name.like(arg("%ABC"))).execute();

其中表操作对象中还包含了其他的快捷方法, 如

//通过实体更新行,返回是否更新成功
boolean update(Person person) {
    //清除其他的where条件和set值
    Integer count = this.update()
                        .where(PersonTable.id.eq(person.getId()))
                        .setName(person.getName())
                        .setAge(person.getAge())
                        .execute();
    return count > 0;
}
//只更新主键对应的行,返回是否更新成功
boolean updateById(Integer id) {
    //清除其他的where条件
    Integer count = this.update().where(PersonTable.id.eq(id)).execute();
    return count > 0;
}

//根据主键删除(快捷方法),返回是否删除成功
boolean deleteById(Integer id) {
    //清除其他的where条件
    Integer count = this.delete().where(PersonTable.id.eq(id)).execute();
    return count > 0;
}

//根据主键查找(快捷方法)
Person findById(Integer id) {
    //清除其他的where条件
    return this.where(PersonTable.id.eq(id)).findOne()
}

表达式-Expression

上如所示, where 函数中要求返回类型是一个表达式

其定义如下:

interface Expression {
    //将表达式转换成SQL片段
    String toSQL();

    //默认快捷函数
    default AndExpression and(Expression right);
    default OrExpression or(Expression right);
    default LikeExpression like(Expression exp);
}
列表达式-ColumnExpression

代表了表中的列, 如:

class ColumnExpression implements Expression {
    String name;
    String toSQL() {
        return name;
    }
}
逻辑表达式-LogicalExpression
class LogicalExpression implements Expression {

}

class AndExpression extends LogicalExpression {
    Expression left;
    Expression right;
    String toSQL() {
        return "(" + left.toSQL() + ")" + " and " + "(" + right.toSQL() + ")"
    }
}

//...

SqlEx Method方法参数强类型化

该设计旨在于增强SqlEx Method参数的类型安全

支持参数类型

1. 预支持类型

// 基本类型
java.lang.Boolean, java.lang.Byte,
java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Float, java.lang.Double,
java.math.BigDecimal, java.math.BigInteger,

//字符 / 二进制数据
java.lang.Character, java.lang.String,
java.lang.Byte[], java.sql.Blob, java.io.InputStream, java.io.Reader

//时间
java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Date,
java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime,
java.time.OffsetTime, java.time.OffsetDateTime, java.time.ZonedDateTime, java.time.Instant,

2. 自定义类型

参数转换器接口

public interface ParameterConverter<P, D> {
    D convert(P parameter);
}

如果类型FooBar要作为参数, 则必须为其定义参数转换器, 并在SqlEx Config中注册

FooBarParameterConverter.java

package me.danwi.sqlex.example.dao.converters;

class FooBarParameterConverter<FooBar, String> {
    String convert(FooBar value) {
        // ...
    }
}

sqlex.yaml 配置文件

# 根包
package: me.danwi.sqlex.exmaple.dao

# 类型转换器
converters:
  - me.danwi.sqlex.example.dao.converters.FooBarParameterConverter
 

converters 列表在上面的转换器优先级高于下面转换器

任务列表

  • core - 完成ParameterConverter的定义(#39 #40)
  • 编辑器插件 - sqlm参数类型错误提示(#47)
  • 编辑器插件 - 配置文件智能支持(#42 #45)
  • 编辑器插件 - 编写自定义类型转换器时的错误提示(#44)
  • 编译插件 - 编译时的类型check(#53)
  • 编译插件 - 把转换器配置通过注解放入生成的Repository接口中(#46)

框架参数类型转换列表

JDBC 原生支持参数类型转换

JDBC方法签名 JAVA类型 SQL类型 备注
void setBoolean(int parameterIndex, boolean x) java.lang.Boolean BIT
BOOLEAN
void setByte(int parameterIndex, byte x) java.lang.Byte TINYINT
void setShort(int parameterIndex, short x) java.lang.Short SMALLINT
void setInt(int parameterIndex, int x) java.lang.Integer INTEGER
void setLong(int parameterIndex, long x) java.lang.Long BIGINT
void setFloat(int parameterIndex, float x) java.lang.Float REAL
void setDouble(int parameterIndex, double x) java.lang.Double DOUBL
void setBigDecimal(int parameterIndex, BigDecimal x) java.math.BigDecimal NUMERIC
void setString(int parameterIndex, String x) java.lang.String VARCHAR
LONGVARCHAR
void setBytes(int parameterIndex, byte x[]) java.lang.Byte[] VARBINARY
LONGVARBINARY
void setAsciiStream(int parameterIndex, java.io.InputStream x, int length) java.io.InputStream LONGVARCHAR
void setUnicodeStream(int parameterIndex, java.io.InputStream x,int length) java.io.InputStream LONGVARCHAR 编码必须是UTF-8
void setBinaryStream(int parameterIndex, java.io.InputStream x,int length) java.io.InputStream LONGVARBINARY
void setDate(int parameterIndex, java.sql.Date x) java.sql.Date DATE jvm默认时区
void setTime(int parameterIndex, java.sql.Time x) java.sql.Time TIME jvm默认时区
void setTimestamp(int parameterIndex, java.sql.Timestamp x) java.sql.Timestamp TIMESTAMP jvm默认时区
void setDate(int parameterIndex, java.sql.Date x, Calendar cal) java.sql.Date DATE JDBC 2.0 Calendar指定时区
void setTime(int parameterIndex, java.sql.Time x, Calendar cal) java.sql.Time TIME JDBC 2.0 Calendar指定时区
void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) java.sql.Timestamp TIMESTAMP JDBC 2.0 Calendar指定时区
void setRef (int parameterIndex, Ref x) java.sql.Ref REF JDBC 2.0
void setBlob (int parameterIndex, Blob x) java.sql.Blob BLOB JDBC 2.0
void setClob (int parameterIndex, Clob x) java.sql.Clob CLOB JDBC 2.0
void setArray (int parameterIndex, Array x) java.sql.Array ARRAY JDBC 2.0
void setCharacterStream(int parameterIndex,java.io.Reader reader,int length) java.io.Reader LONGVARCHAR JDBC 2.0 大UNICODE使用
void setURL(int parameterIndex, java.net.URL x) java.net.URL DATALINK JDBC 3.0
void setNString(int parameterIndex, String value) java.lang.String NCHAR
NVARCHAR
LONGNVARCHAR
JDBC 4.0
void setRowId(int parameterIndex, RowId x) java.sql.RowId ROWID JDBC 4.0
void setNClob(int parameterIndex, NClob value) java.sql.NClob NCLOB JDBC 4.0
void setSQLXML(int parameterIndex, SQLXML xmlObject) java.sql.SQLXML XML JDBC 4.0
void setBlob(int parameterIndex, InputStream inputStream, long length) java.io.InputStream BLOB
LONGVARBINARY
JDBC 4.0
void setClob(int parameterIndex, Reader reader, long length) java.io.Reader CLOB JDBC 4.0
void setNClob(int parameterIndex, Reader reader, long length) java.io.Reader LONGNVARCHAR
NCLOB
JDBC 4.0
void setAsciiStream(int parameterIndex, java.io.InputStream x, long length) java.io.InputStream LONGVARCHAR JDBC 4.0
When a very large ASCII value is input to a LONGVARCHAR parameter
void setBinaryStream(int parameterIndex, java.io.InputStream x,long length) java.io.InputStream LONGVARBINARY JDBC 4.0
When a very large binary value is input to a LONGVARBINARY parameter
void setCharacterStream(int parameterIndex,java.io.Reader reader,long length) java.io.Reader LONGVARCHAR JDBC 4.0
When a very large UNICODE value is input to a LONGVARCHAR parameter
void setAsciiStream(int parameterIndex, java.io.InputStream x) java.io.InputStream LONGVARCHAR JDBC 4.0
void setBinaryStream(int parameterIndex, java.io.InputStream x) java.io.InputStream LONGVARBINARY JDBC 4.0
void setCharacterStream(int parameterIndex,java.io.Reader reader) java.io.Reader LONGVARCHAR JDBC 4.0
When a very large UNICODE value is input to a LONGVARCHAR parameter
void setNCharacterStream(int parameterIndex, Reader value) java.io.Reader LONGVARCHAR JDBC 4.0
void setNCharacterStream(int parameterIndex, Reader value, long length) java.io.Reader LONGVARCHAR JDBC 4.0
void setClob(int parameterIndex, Reader reader) java.io.Reader CLOB
LONGVARCHAR
JDBC 4.0
void setBlob(int parameterIndex, InputStream inputStream) java.io.InputStream LONGVARBINARY
BLOB
JDBC 4.0
void setNClob(int parameterIndex, Reader reader) java.io.Reader LONGNVARCHAR
NCLOB
JDBC 4.0

扩展支持常用JAVA类型参数转换

JDBC没有,但是经常用的类型,支持自定义实现转换

JAVA类型 SQL类型
java.math.BigInteger NUMERIC
java.time.LocalDate DATE
java.time.LocalTime TIME
java.time.LocalDateTime TIMESTAMP
java.util.Date DATE

IDEA 2022.3 构建错误

sqlex版本:0.11.12
idea 版本:2022.3.1
jdk版本:1.8

java.lang.UnsatisfiedLinkError: Unable to locate JNA native support library
	at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:1018)
	at com.sun.jna.Native.<clinit>(Native.java:221)
	at com.sun.jna.Structure.setAlignType(Structure.java:291)
	at com.sun.jna.Structure.<init>(Structure.java:208)
	at com.sun.jna.Structure.<init>(Structure.java:204)
	at com.sun.jna.Structure.<init>(Structure.java:191)
	at com.sun.jna.Structure.<init>(Structure.java:183)
	at me.danwi.sqlex.parser.ffi.GoString.<init>(GoString.java:12)
	at me.danwi.sqlex.parser.ffi.GoString$ByValue.<init>(GoString.java:14)
	at me.danwi.sqlex.parser.Session.<init>(Session.kt:116)
	at me.danwi.sqlex.parser.RepositoryBuilder.<init>(Repository.kt:28)
	at me.danwi.sqlex.idea.repositroy.SqlExRepositoryService$refresh$1$1.run(SqlExRepositoryService.kt:150)
	at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:423)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:114)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$6(CoreProgressManager.java:474)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$3(ProgressRunner.java:252)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:188)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$13(CoreProgressManager.java:589)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:664)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:620)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:588)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:175)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:252)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
	at java.base/java.lang.Thread.run(Thread.java:833)

db[json] -> java 映射失败!!!

IDEA 版本: 2023.3.3
工程:�gradle-example

me.danwi.sqlex.parser.exception.SqlExRepositoryMethodException: db[json] -> java 映射失败!!!
	at me.danwi.sqlex.parser.generate.GeneratedJavaFile$source$2.invoke(GeneratedJavaFile.kt:31)
	at me.danwi.sqlex.parser.generate.GeneratedJavaFile$source$2.invoke(GeneratedJavaFile.kt:21)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at me.danwi.sqlex.parser.generate.GeneratedJavaFile.getSource(GeneratedJavaFile.kt:21)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository$generateJavaPsiClass$$inlined$runReadAction$1.compute(Thread.kt:30)
	at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:894)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository.generateJavaPsiClass(SqlExRepository.kt:185)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository.access$generateJavaPsiClass(SqlExRepository.kt:20)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository$entityJavaClassCaches$2.invoke(SqlExRepository.kt:31)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository$entityJavaClassCaches$2.invoke(SqlExRepository.kt:28)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository.getEntityJavaClassCaches(SqlExRepository.kt:28)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository.getAllJavaClassCache(SqlExRepository.kt:62)
	at me.danwi.sqlex.idea.repositroy.SqlExRepository.findClassByName(SqlExRepository.kt:159)
	at me.danwi.sqlex.idea.interpreter.SqlExGeneratedShortNamesCache.getClassesByName(SqlExGeneratedShortNamesCache.kt:16)
	at com.intellij.psi.impl.CompositeShortNamesCache.getClassesByName(CompositeShortNamesCache.java:68)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver.findPotentialClassConflicts(PsiBasedClassResolver.kt:94)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver.access$findPotentialClassConflicts(PsiBasedClassResolver.kt:32)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver$1.invoke(PsiBasedClassResolver.kt:88)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver$1.invoke(PsiBasedClassResolver.kt:87)
	at com.intellij.openapi.application.ActionsKt.runReadAction$lambda$3(actions.kt:31)
	at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:894)
	at com.intellij.openapi.application.ActionsKt.runReadAction(actions.kt:31)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver.<init>(PsiBasedClassResolver.kt:87)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver.<init>(PsiBasedClassResolver.kt)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver$Companion.getInstance$lambda$1(PsiBasedClassResolver.kt:69)
	at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:37)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:240)
	at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:43)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:240)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:27)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:66)
	at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:241)
	at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:27)
	at org.jetbrains.kotlin.idea.search.PsiBasedClassResolver$Companion.getInstance(PsiBasedClassResolver.kt:77)
	at org.jetbrains.kotlin.idea.base.searching.KotlinAnnotatedElementsSearcher$Companion.processAnnotatedMembers(KotlinAnnotatedElementsSearcher.kt:93)
	at org.jetbrains.kotlin.idea.base.searching.KotlinAnnotatedElementsSearcher$Companion.processAnnotatedMembers$default(KotlinAnnotatedElementsSearcher.kt:85)
	at org.jetbrains.kotlin.idea.base.searching.KotlinAnnotatedElementsSearcher.execute(KotlinAnnotatedElementsSearcher.kt:48)
	at org.jetbrains.kotlin.idea.base.searching.KotlinAnnotatedElementsSearcher.execute(KotlinAnnotatedElementsSearcher.kt:45)
	at com.intellij.util.ExecutorsQuery.processResults(ExecutorsQuery.java:30)
	at com.intellij.util.AbstractQuery.doProcessResults(AbstractQuery.java:83)
	at com.intellij.util.AbstractQuery.delegateProcessResults(AbstractQuery.java:100)
	at com.intellij.util.InstanceofQuery.processResults(InstanceofQuery.java:22)
	at com.intellij.util.AbstractQuery.doProcessResults(AbstractQuery.java:83)
	at com.intellij.util.AbstractQuery.forEach(AbstractQuery.java:75)
	at com.intellij.jam.model.util.JamCommonUtil.findAnnotatedElements(JamCommonUtil.java:386)
	at com.intellij.jam.JamService.getJamClassElements(JamService.java:184)
	at com.intellij.jam.JamService.getJamClassElements(JamService.java:126)
	at com.intellij.spring.model.utils.SpringCommonUtils.lambda$getPropertySources$8(SpringCommonUtils.java:519)
	at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:37)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:240)
	at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:43)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:240)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:27)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:66)
	at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:241)
	at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:27)
	at com.intellij.util.CachedValuesManagerImpl.getCachedValue(CachedValuesManagerImpl.java:69)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:111)
	at com.intellij.spring.model.utils.SpringCommonUtils.getPropertySources(SpringCommonUtils.java:509)
	at com.intellij.spring.boot.model.SpringBootConfigurationFileServiceImpl.lambda$findPropertySources$2(SpringBootConfigurationFileServiceImpl.java:140)
	at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:37)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:240)
	at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:43)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:240)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:27)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:66)
	at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:241)
	at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:27)
	at com.intellij.util.CachedValuesManagerImpl.getCachedValue(CachedValuesManagerImpl.java:69)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:111)
	at com.intellij.spring.boot.model.SpringBootConfigurationFileServiceImpl.findPropertySources(SpringBootConfigurationFileServiceImpl.java:139)
	at com.intellij.spring.boot.model.SpringBootConfigurationFileServiceImpl.isPropertySource(SpringBootConfigurationFileServiceImpl.java:67)
	at com.intellij.spring.boot.model.SpringBootConfigurationFileServiceImpl.isApplicationConfigurationFile(SpringBootConfigurationFileServiceImpl.java:49)
	at com.intellij.spring.boot.application.yaml.SpringBootApplicationYamlUtil.isInsideApplicationYamlFile(SpringBootApplicationYamlUtil.java:16)
	at com.intellij.spring.boot.application.yaml.SpringBootApplicationYamlReferenceContributor$1.accepts(SpringBootApplicationYamlReferenceContributor.java:27)
	at com.intellij.spring.boot.application.yaml.SpringBootApplicationYamlReferenceContributor$1.accepts(SpringBootApplicationYamlReferenceContributor.java:20)
	at com.intellij.patterns.ObjectPattern.accepts(ObjectPattern.java:48)
	at com.intellij.psi.impl.source.resolve.reference.NamedObjectProviderBinding.addMatchingProviders(NamedObjectProviderBinding.java:90)
	at com.intellij.psi.impl.source.resolve.reference.SimpleProviderBinding.addAcceptableReferenceProviders(SimpleProviderBinding.java:26)
	at com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl.getPairsByElement(PsiReferenceRegistrarImpl.java:187)
	at com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl.doGetReferencesFromProviders(ReferenceProvidersRegistryImpl.java:142)
	at com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry.lambda$getReferencesFromProviders$0(ReferenceProvidersRegistry.java:44)
	at com.intellij.psi.util.CachedValuesManager$1.compute(CachedValuesManager.java:158)
	at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:37)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:240)
	at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:43)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:240)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:27)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:66)
	at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:241)
	at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:27)
	at com.intellij.util.CachedValuesManagerImpl.getCachedValue(CachedValuesManagerImpl.java:69)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:155)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:121)
	at com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry.getReferencesFromProviders(ReferenceProvidersRegistry.java:42)
	at com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry.getReferencesFromProviders(ReferenceProvidersRegistry.java:35)
	at org.jetbrains.yaml.psi.impl.YAMLScalarImpl.getReferences(YAMLScalarImpl.java:63)
	at com.intellij.psi.PsiReferenceServiceImpl.doGetReferences(PsiReferenceServiceImpl.java:37)
	at com.intellij.psi.PsiReferenceServiceImpl.getReferences(PsiReferenceServiceImpl.java:25)
	at com.intellij.codeInsight.highlighting.HyperlinkAnnotator.lambda$getReferences$0(HyperlinkAnnotator.java:75)
	at com.intellij.psi.util.CachedValuesManager$1.compute(CachedValuesManager.java:158)
	at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:37)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:240)
	at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:43)
	at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:240)
	at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:111)
	at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:27)
	at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:66)
	at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:241)
	at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:27)
	at com.intellij.util.CachedValuesManagerImpl.getCachedValue(CachedValuesManagerImpl.java:69)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:155)
	at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:121)
	at com.intellij.codeInsight.highlighting.HyperlinkAnnotator.getReferences(HyperlinkAnnotator.java:74)
	at com.intellij.codeInsight.highlighting.HyperlinkAnnotator.annotateContributedReferences(HyperlinkAnnotator.java:58)
	at com.intellij.codeInsight.highlighting.HyperlinkAnnotator.annotate(HyperlinkAnnotator.java:53)
	at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.runAnnotators(DefaultHighlightVisitor.java:128)
	at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.visit(DefaultHighlightVisitor.java:106)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.runVisitors(GeneralHighlightingPass.java:361)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$collectHighlights$7(GeneralHighlightingPass.java:292)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:321)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$analyzeByVisitors$8(GeneralHighlightingPass.java:324)
	at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.analyze(DefaultHighlightVisitor.java:91)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:324)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectHighlights(GeneralHighlightingPass.java:287)
	at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectInformationWithProgress(GeneralHighlightingPass.java:234)
	at com.intellij.codeInsight.daemon.impl.ProgressableTextEditorHighlightingPass.doCollectInformation(ProgressableTextEditorHighlightingPass.java:80)
	at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:55)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$1(PassExecutorService.java:406)
	at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.runWithSpanIgnoreThrows(trace.kt:76)
	at com.intellij.platform.diagnostic.telemetry.helpers.TraceUtil.runWithSpanThrows(TraceUtil.java:34)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:401)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1075)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$3(PassExecutorService.java:392)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:610)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:685)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:641)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:609)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:78)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:391)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:367)
	at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:200)
	at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:184)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:365)
	at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:187)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

异常处理设计

原则

SqlEx 异常设计遵从以下原则

  • SqlEx中所有的异常均为RuntimeException
  • 异常均不淹没(getCause)

SqlEx自有异常

  • SqlExRepositoryNotMatchException 当DaoFactory获取DAO实例时,传入的DAO类型和Repository不匹配
  • SqlExImpossibleException 不可能出现的异常,因为SqlEx保证了编译时安全,该异常不可能出现. 如果出现了该异常,要么是编译时检查有问题,要么就是使用者通过非法手段(强行反射调用等)调用框架功能

异常转换/翻译

DaoFactory提供ExceptionTranslator参数,方便自定义异常的转换和包装

目前已经提供如下两个translator

1. DefaultExceptionTranslator

默认转换器,不显式指定时将使用该转换/翻译器

  • SqlEx执行过程中发生的SQLException将会被SqlExSQLException包装
  • DaoFactory.transaction的lambda函数执行过程中的Checked异常(SQLException除外)将会被SqlExUndeclaredException包装
  • 其他RuntimeException不变

2. SpringExceptionTranslator

Spring提供的异常翻译/转换器,与DefaultExceptionTranslator唯一不同即是SQLException将会被转换成DataAccessException

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.