# fastquery **Repository Path**: zmyer/fastquery ## Basic Information - **Project Name**: fastquery - **Description**: Fast Query 基于Java语言. 他的使命是:简化Java操作数据层.做为一个开发者,仅仅只需要设计编写DAO接口即可,其内部采用ASM动态生成实现,执行快. 因此,代码简洁而优雅.从而,大幅度提升开发效率. - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 67 - **Created**: 2016-05-22 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FastQuery 数据持久层框架 FastQuery 基于Java语言.他的使命是:简化Java操作数据层.
做为一个开发者, **仅仅只需要设计DAO接口即可**,其内部采用ASM动态生成实现,执行快. 因此,代码简洁而优雅.从而,大幅度提升开发效率.
遵循非侵入式原则设计,松耦合,很容易与其它容器或框架集成.
提供了一组简单的`Annotation`.消费者只用关心注解的含义.这就使得框架的核心便于重构,便于持续良性发展.
## FastQuery 主要特性如下: 1. 设计优雅,配置简单,极易上手. 2. 采用ASM动态生成字节码,因此支持编译前预处理,可最大限度减少运行期的错误.显著提升程序的强壮性. 3. 支持安全查询,防止SQL注入. 4. 支持与主流数据库连接池框架集成,如集成c3p0,dbcp等等 5. 支持 `@Query` 查询,使用 `@Condition`,可实现动态 `where` 条件查询. 6. 支持查询结果集以JSON类型返回 7. 支持`AOP`,注入拦截器只需标识几个简单的注解,如: `@Before` , `@After` ## 运行环境要求 jdk1.8+ ## 配置文件 ### jdbc-config.xml 用来配置支持jdbc. **注意**:如果采用连接池,该配置文件可以不要. ```xml com.mysql.jdbc.Driver jdbc:mysql://192.168.1.1:3306/xk?user=xk&password=abc123 com.mysql.jdbc.Driver dbname username userpasswd 3306 192.168.1.1 ``` ### c3p0-config.xml 支持c3p0配置,详情配置请参照c3p0官网的说明. ```xml com.mysql.jdbc.Driver jdbc:mysql://192.168.1.1:3306/xk xk abc123 50 100 50 1000 0 5 ``` ### fastquery.json 配置数据源的作用范围 ```js // @author xixifeng (fastquery@126.com) // 配置必须遵循标准的json语法. [ // config目前支持的可选值有"jdbc","c3p0" { "config": "c3p0", // 表示由c3p0负责提供数据源 "dataSourceName": "xk-c3p0", // 数据源的名称 "basePackages": [ // 该数据源的作用范围 "org.fastquery.example.StudentDBService", "org.fastquery.example.UserInfoDBService" // 在这可以配置多个DB接口,以","号隔开 ] }, /* 再配置一个数据源作用域 */ { "config" : "jdbc", // 表示由jdbc驱动负责提供数据源 "dataSourceName": "shtest_db", // 数据源的名称 "basePackages": [ // 该数据源的作用范围 "org.fastquery.example.DataAcquireDbService" // 在这可以配置多个DB接口,以","号隔开 ] } ] ``` ## 一个完整的入门例子 - 准备一个实体 ```java public class Student { private String no; private String name; private String sex; private Integer age; private String dept; // getter /setter 省略... } ``` - DAO接口 ```java public interface StudentDBService extends QueryRepository { @Query("select * from student") JSONArray findAll(); @Query("select * from student") Student[] find(); } ``` - 使用DAO接口. **注意**:不用去实现StudentDBService接口. ```java // get porxy impl StudentDBService studentDBService = FQuery.getRepository(StudentDBService.class); // call findAll JSONArray jsonArray = studentDBService.findAll(); // call find Student[] students = studentDBService.find(); ``` ## 带条件查询 ```java // sql中的?1 表示当前方法的第一个参数 // sql中的?2 表示当前方法的第二个参数 // ?N 表示当前方法的第N个参数 // 查询返回数组格式 @Query("select no as no,name,sex,age,dept from student s where s.sex=?2 and s.age > ?1") Student[] find(Integer age,String sex); // 查询返回JSON格式 @Query("select * from student s where s.sex=?1 and s.age > ?2") JSONArray find(String sex,Integer age); // 查询返回List Map @Query("select * from student s where s.sex=?1 and s.age > ?2") List> findBy(String sex,Integer age); ``` ## 动态条件查询 ```java @Query("select * from Student #{#where} order by age desc") // 增加一些条件 @Condition(l="no",o=Operator.LIKE,r="?1") // ?1的值,如果是null, 该行条件将不参与运算 @Condition(c=COperator.AND,l="name",o=Operator.LIKE,r="?2") // 参数 ?2,如果接收到的值为null,该条件不参与运算 // 通过 ignoreNull=false 开启条件值即使是null也参与运算 // 下行?3接收到的值若为null,该条件也参与运算. @Condition(c=COperator.AND,l="age",o=Operator.GT,r="?3",ignoreNull=false) @Condition(c=COperator.OR,l="dept",o=Operator.IN,r="(?4,?5,?6)") // dept in(?4,?5,?6) @Condition(c=COperator.AND,l="name",o={Operator.NOT,Operator.LIKE},r="?7") // 等效于 name not like ?7 @Condition(c=COperator.OR,l="age",o=Operator.BETWEEN,r="?8 and ?9") // 等效于 age between ?8 and ?9 Student[] findAllStudent(... args ...); ``` ## count 统计查询行数 ```java @Query("select count(no) from student") long count(); ``` ## exists 判断是否存在 ```java @Query("select * from student s where s.no=?1") boolean exists(String no); ``` ## 改操作 ```java @Query("update student s set s.age=?3,s.name=?2 where s.no=?1") @Modifying int update(String no,String name,int age); // 返回修改之后所影响的行数 @Modifying @Query("DELETE FROM `userinfo` WHERE id=?1") boolean deleteUserinfoById(int id); @Query("update student s set s.age=?2 where s.no=?1") @Modifying int update(String no,int age); // 以实体bean格式,返回当前保存的数据 @Query("insert into student (no, name, sex, age, dept) values (?1, ?2, ?3, ?4, ?5)") @Modifying(table="student",id="no") // 注意: student的主键是字符串不会自增长,在此处需要用@Id标识 Student addStudent(@Id String no,String name,String sex,int age,String dept); // 以Map格式,返回当前保存的数据 @Modifying(id="id",table="userinfo") @Query("insert into #{#table} (name,age) values (?1, ?2)") Map addUserInfo(String name,Integer age); // 以JSON格式,返回当前保存的数据 @Modifying(id="id",table="userinfo") @Query("insert into #{#table} (name,age) values (?1, ?2)") JSONObject saveUserInfo2(String name,Integer age); // 返回当前保存的数据的主键信息. @Modifying(id="id",table="userinfo") @Query("insert into #{#table} (name,age) values (?1, ?2)") Primarykey saveUserInfo(String name,Integer age); ``` ## @Transactional ```java // 将三条改操作纳入到一个事务中. @Transactional @Modifying @Query("update `userinfo` set `name`=?1 where id=?3") @Query("update `userinfo` set `age`=?2 where id=?3") // 把主键id修改为1,目前主键id=1是存在的.这行会报错.那么前两行所做的操作全部失效. @Query("update `userinfo` set `id`=1 where `id`=?3") int updateBatch(String name,Integer age,Integer id); // 注意: // 1).返回值如果是int类型,表示这个事务成功提交后所有改操作所影响的行数总和. // 2).返回值如果是int[]类型,表示这个事务成功提交后,每个最小修改单元所影响行数的集合. // 举例说明: 若有个事务T,它里面有3条改操作,分别叫U1,U2,U3. T成功提交后,U1,U2,U3所影响的数据行数分别为N1,N2,N3. // 则: 返回值为: new int[]{N1,N2,N3} ``` ## @Before拦截器 - 准备一个BeforeFilter ```java /** * @author xixifeng (fastquery@126.com) */ public class MyBeforeFilter1 extends BeforeFilter { @Override public void doFilter(Repository repository, Method method, Object[] args) { // repository: 当前拦截到的实例 // method: 当前拦截到的方法 // args: 当前传递进来的参数 // this.abortWith(returnVal); // 中断拦截器,并指定返回值 } } ``` - 注入Filter ```java // 可以同时标识多个@Before @Before(MyBeforeFilter1.class) @Before(MyBeforeFilter2.class) @Before(MyBeforeFilter3.class) public interface StudentDBService extends QueryRepository { // some code ... ... } ``` ## @After拦截器 ```java /** * @author xixifeng (fastquery@126.com) */ public class MyAfterFilter extends AfterFilter { @Override public Object doFilter(Repository repository, Method method, Object[] args, Object returnVal) { // repository: 当前拦截到的实例 // method: 当前拦截到的method // args: 当前传递进来的参数 // returnVal 即将返回的值 // 在这里可以中途修改 returnVal return returnVal; } } ``` ```java // 可以同时标识多个@After @After(MyAfterFilter.class) @After(MyAfterFilter2.class) public interface StudentDBService extends QueryRepository { // some code ... ... } ``` ## 控制拦截器的作用域 若: 有一个拦截器叫`A`,那么:这个拦截器的作用范围只能在`T`类或`T`的子类里.
举例: ```java // 这个拦截器的作用范围在 DataAcquireDbService里或在DataAcquireDbService子类里. // 换言之: MyBeforeFilter3这个拦截器只能标注在DataAcquireDbService里或标注在DataAcquireDbService的子类里. public class MyBeforeFilter3 extends BeforeFilter { // some code ... ... } ``` ### 注意: - `@Before`和`@After`不仅可以标注在接口类上,也可以标注在方法上 - 标识在类的上方:表示其拦截的作用范围是整个类的方法 - 标识在方法上:表示其拦截的作用范围是当前方法 - 一个方法的拦截器总和=它的所属类的拦截器+自己的拦截器 ## 源码 - http://git.oschina.net/xixifeng.com/fastquery - https://github.com/xixifeng/fastquery - https://code.aliyun.com/xixifeng/fastquery ## 联系作者 fastquery#126.com 欢迎批评指正.