专业的编程技术博客社区

网站首页 > 博客文章 正文

Wood:微型 Java ORM 框架,跨平台、小巧、无依赖!

baijin 2024-08-08 23:02:30 博客文章 59 ℃ 0 评论

#挑战30天在头条写日记#

微型ORM框架(支持:java sql,xml sql,annotation sql;事务;缓存;监控;等...),无依赖!

特点和理念:

  • 跨平台:可以嵌入到JVM脚本引擎(js, groovy, lua, python, ruby)及GraalVM支持的部分语言。
  • 很小巧:0.2Mb(且是功能完整,方案丰富;可极大简化数据库开发)。
  • 有个性:不喜欢反射(主打弱类型)、不喜欢配置(除了连接,不需要其它配置)。
  • 其它的:支持缓存控制和跨数据库事务。

核心对象和功能:

  • 上下文:DbContext db
  • 四个接口:db.mapper(), db.table(), db.call(), db.sql()
//BaseMapper 接口
db.mapperBase(User.class).selectById(1);

//BaseMapper 接口,lambda 条件查询
db.mapperBase(User.class).selectList(mq->mq
        .whereLt(User::getGroup,1)
        .andEq(User::getLabel,"T"));


//Table 接口
db.table("user u")
  .innerJoin("user_ext e").onEq("u.id","e.user_id")
  .whereEq("u.type",11)
  .limit(100,20)
  .selectList("u.*,e.sex,e.label", User.class);

db.table("user u")
  .innerJoin("user_ext e").onEq("u.id","e.user_id")
  .whereEq("u.type",11)
  .limit(100,20)
  .selectAsCmd("u.*,e.sex,e.label"); //构建查询命令(即查询语句)

//Table 接口,拼装条件查询(特别适合管理后台)
db.table(logger)
  .where("1 = 1")
  .andIf(TextUtils.isNotEmpty(trace_id), "trace_id = ?", trace_id)
  .andIf(TextUtils.isNotEmpty(tag), "tag = ?", tag)
  .andIf(TextUtils.isNotEmpty(tag1), "tag1 = ?", tag1)
  .andIf(TextUtils.isNotEmpty(tag2), "tag2 = ?", tag2)
  .andIf(TextUtils.isNotEmpty(tag3), "tag3 = ?", tag3)
  .andIf(log_date > 0, "log_date = ?", log_date)
  .andIf(log_id > 0, "log_id <= ?", log_id)
  .andIf(level > 0, "level=?", level)
  .orderBy("log_fulltime desc")
  .limit(size)
  .selectList("*", LogModel.class);

组件列表:

组件

说明

org.noear:wood

主框架(没有任何依赖)

org.noear:wood.plus

增强框架(支持 Mapper 和 XmlMapper)

可选组件

说明

org.noear:wood-maven-plugin

Maven插件,用于生成 XmlMapper



org.noear:wood.cache.memcached

基于 Memcached 适配的扩展缓存服务

org.noear:wood.cache.redis

基于 Redis 适配的扩展缓存服务

org.noear:wood.cache.ehcache

基于 ehcache 适配的扩展缓存服务

org.noear:wood.cache.j2cache

基于 j2cache 适配的扩展缓存服务

Meven配置:

<!-- 框架包 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>wood</artifactId>
    <version>1.2.0</version>
</dependency>

<!-- 可选:maven 插件,用于生成Xml sql mapper接口 -->
<plugin>
    <groupId>org.noear</groupId>
    <artifactId>wood-maven-plugin</artifactId>
    <version>1.2.0</version>
</plugin>

入门示例:

/** 1.实例化上下文 */
//DbContext db  = new DbContext(properties); //使用Properties配置的示例
//DbContext db  = new DbContext(map); //使用Map配置的示例
//DbContext db  = new DbContext("user","proxool.xxx_db"); //使用proxool线程池配置的示例
//DbContext db  = new DbContext("user","jdbc:mysql://x.x.x:3306/user","root","1234");
DbContext db  = new DbContext("user",new HikariDataSource(...)); //使用DataSource配置的示例

/** 2.1.Mapper用法 */
@Namespace("demo.dso.db")
public interface UserDao extends BaseMapper<UserModel>{
    @Sql("select * from user where id=@{id} limit 1")
    UserModel getUser(int id);
  
    @Sql("select * from user where id=? limit 1")
    UserModel getUser2(int id);

    void addUser(UserModel user); //没注解,需要配xml
}

UserDao userDao = db.mapper(UserDao.class);
//调用 BaseMapper 方法
userDao.selectById(12); 

//调用 @Sql 方法
UserModel user = userDao.getUser(2); 

//调用 Xml sql
userDao.addUser(user); 

//调用Template sql
StatModel stat = userDao.userStat(20201010);



/** 2.2.Table用法 */
//增::
db.table("user").setEntity(user).insert();
db.table("user").setMap(map).insert();
db.table("user").setMap(map).insertAsCmd(); //构建查询命令(即查询语句)
//删::
db.table("user").whereEq("id",2).delete();
//改::
db.table("user").set("sex",1).whereEq("id",2).update();
db.table("user").setInc("level",1).whereEq("id",2).update(); //字段自+1
//查::
db.table("user u")
  .innerJoin("user_ext e").onEq("u.id","e.user_id")
  .whereEq("u.id",1001)
  .selectItem("u.*,e.sex,e.label", User.class);

//查++(折开来拼接条件)::
var tb = db.table("user u");
if(test.a){
  tb.innerJoin("user_ext e").onEq("u.id","e.user_id");
}

if(test.b){
  tb.whereEq("u.id",1001);
}

tb.selectItem("u.*,e.sex,e.label", User.class);

//查++2(通过构建函数拼接条件)::
db.table("user u")
  .build(tb->{
    if(test.a){
      tb.innerJoin("user_ext e").onEq("u.id","e.user_id"); 
    }
       
    if(test.b){
      tb.whereEq("u.id",1001);
    }
  }).selectItem("u.*,e.sex,e.label", User.class);

/** 2.3.Call用法 */
//调用存储过程
db.call("user_get_list_by").set("_type",12).getList(User.class);

//调用xml sql
db.call("@demo.dso.db.user_get").set("id",1001).getItem(User.class);


/** 2.4.Sql用法 */
//快速执行SQL语句
db.sql("select * from user id=?",12).getItem(User.class);

附:语法参考:

(一)Xml sql 语法

  • 示例
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//noear.org//DTD Mapper 3.0//EN" "http://noear.org/dtd/wood-mapper.dtd">
<mapper namespace="wood_demo.xmlsql2"
        import="demo.model.*"
        baseMapper="UserModel">
    <sql id="getUser" return="UserModel" remarks="获取用户信息">
        SELECT * FROM user WHERE id = @{id:int}
    </sql>
</mapper>
  • 具体参考:《WOOD XML 语法》

(二)Table 语法

  • 条件操作(与Mapper共享)

方法

效果说明

where, whereIf


whereEq, whereNeq

==, !=

whereLt, whereLte

<, <=

whereGt, whereGte

>, >=

whereLk, whereNlk

LIKE, NOT LIKE

whereIn, whereNin

IN(..), NOT IN(..)

whereBtw, whereNbtw

BETWEEN, NOT BETWEEN

and系统方法

同where

or系统方法

同where

begin

(

end

)

  • 表操作(Table独占)

方法

效果说明

set, setIf

设置值

setMap, setMapIf

设置值

setEntity, setEntityIf

设置值

table

主表

innerJoin, leftJoin, rightJoin

关联表

on, onEq

关联条件

orderBy, orderByAsc, orderByDesc

排序

groupBy

having

组条件

limit

限制范围

select

查询(返回IQuery)

count

查询快捷版,统计数量

exists

查询快捷版,是否存在

update

更新

insert

插入

delete

删除

Wood JAVA 接口字典

db.mapper(clz) -> SqlMapper? proxy

  • db.mapper(XxxMapper.class) -> XxxMapper
  • db.mapperBase(XxxEntity.class) -> BaseMapper<XxxEntity>
  • db.mapper(xsqlid, args) -> Object
//xml sql 和 annotation sql 参考另外的资料

//例1:UserMapper dao = db.mapper(UserMapper.class);
//   UserModel um = dao.getUser(12);

//例2:BaseMapper<User> dao = db.mapperBase(User.class);
//   UserModel um = dao.selectById(12);

//例3:UserModel um = db.mapper("@demo.dao.db.user_get",{app_id:12});

db.table("table") -> new:DbTableQuery

//
// 构建相关
//

-build(builder:(tq)->{}) -> self //通过表达式构建自己

//例: db.table("user u")
//      .with("a","select type num from group by type")
//      .where("u.type in(select a.type) and u.type2 in (select a.type)")
//      .selectMapList("u.*");
-with(name:String,code:String,args:Object...) -> self //添加SQL with 语句

-whereTrue()-> self

//例1: .where("name=?","x")
//例2: .where("((name=? or id=?) and sex=0)","x",1)
-where(code:String,args:Object...) -> self //添加SQL where 语句 //可使用?,?...占位符( ?... 表示数组占位符)
-whereIf(condition:bool, code:String,args:Object...) -> self
-whereMap(map:Map<String,Object>) -> self  //null会默认排除
-whereMapIf(map:Map<String,Object>, condition:(k,v)->bool) -> self
-whereEntity(entity:Object) -> self //null会默认排除
-whereEntityIf(entity:Object, condition:(k,v)->bool) -> self;
-where() -> self //添加SQL where 关键字
-whereEq(col:String,val:Object) -> self //添加SQL where = 语句      //val为null时,转为 IS NULL
-whereNeq(col:String,val:Object) -> self //添加SQL where != 语句    //val为null时,转为 IS NOT NULL
-whereLt(col:String,val:Object) -> self //添加SQL where < 语句
-whereLte(col:String,val:Object) -> self //添加SQL where <= 语句
-whereGt(col:String,val:Object) -> self //添加SQL where > 语句
-whereGte(col:String,val:Object) -> self //添加SQL where >= 语句
-whereLk(col:String,val:String) -> self //添加SQL where like 语句
-whereNlk(col:String,val:String) -> self //添加SQL where not like 语句
-whereBtw(col:String, start:Object, end:Object) -> self //添加SQL where BETWEEN .. AND 语句
-whereNbtw(col:String, start:Object, end:Object) -> self //添加SQL where NOT BETWEEN .. AND 语句
-whereIn(col:String, ary:Iterable)-> self //添加SQL where IN (...) 语句
-whereNin(col:String, ary:Iterable)-> self //添加SQL where not IN (...) 语句

//例1:.and("name=?","x")
//例2: .and("(name=? or id=?)","x",1)
-and(code:String,args:Object...) -> self //添加SQL and 语句 //可使用?,?...占位符( ?... 表示数组占位符)
-andIf(condition:bool, code:String,args:Object...) -> self
-and() -> self //添加SQL and 关键字
-andEq(col:String,val:Object) -> self //添加SQL and = 语句      //val为null时,转为 IS NULL
-andNeq(col:String,val:Object) -> self //添加SQL and != 语句    //val为null时,转为 IS NOT NULL
-andLt(col:String,val:Object) -> self //添加SQL and < 语句
-andLte(col:String,val:Object) -> self //添加SQL and <= 语句
-andGt(col:String,val:Object) -> self //添加SQL and > 语句
-andGte(col:String,val:Object) -> self //添加SQL and >= 语句
-andLk(col:String,val:String) -> self //添加SQL and like 语句
-andNlk(col:String,val:String) -> self //添加SQL and not like 语句
-andBtw(col:String, start:Object, end:Object) -> self //添加SQL and BETWEEN .. AND 语句
-andNbtw(col:String, start:Object, end:Object) -> self //添加SQL and NOT BETWEEN .. AND 语句
-andIn(col:String, ary:Iterable)-> self //添加SQL and IN (...) 语句
-andNin(col:String, ary:Iterable)-> self //添加SQL and not IN (...) 语句

//例1:.or("name=?","x"); 
//例2: .or("(name=? or id=?)","x",1)
-or(code:String,args:Object...) -> self //添加SQL or 语句 //可使用?,?...占位符( ?... 表示数组占位符)
-orIf(condition:bool, code:String,args:Object...) -> self
-or() -> self //添加SQL or 关键字
-orEq(col:String,val:Object) -> self //添加SQL or = 语句        //val为null时,转为 IS NULL
-orNeq(col:String,val:Object) -> self //添加SQL or != 语句      //val为null时,转为 IS NOT NULL
-orLt(col:String,val:Object) -> self //添加SQL or < 语句
-orLte(col:String,val:Object) -> self //添加SQL or <= 语句
-orGt(col:String,val:Object) -> self //添加SQL or > 语句
-orGte(col:String,val:Object) -> self //添加SQL or >= 语句
-orLk(col:String,val:String) -> self //添加SQL or like 语句
-orNlk(col:String,val:String) -> self //添加SQL or not like 语句
-orBtw(col:String, start:Object, end:Object) -> self //添加SQL or BETWEEN .. AND 语句
-orNbtw(col:String, start:Object, end:Object) -> self //添加SQL or NOT BETWEEN .. AND 语句
-orIn(col:String, ary:Iterable)-> self //添加SQL or IN (...) 语句
-orNin(col:String, ary:Iterable)-> self //添加SQL or not IN (...) 语句

-begin() -> self //添加左括号
-begin(code:String,args:Object...) -> self //添加左括号并附加代码//可使用?,?...占位符( ?... 表示数组占位符)
-end() -> self //添加右括号

-set(name:String,value:Object) -> self  //设置变量
-setIf(condition:bool,name:String,value:Object) -> self
-setMap(data:Map<String,Object>) -> self    //设置变量(将map输入)  //null会默认排除
-setMapIf(data:Map<String,Object>,(k,v)->bool) -> self
-setEntity(data:Object) -> self     //设置变量(将实体输入) //null会默认排除
-setEntityIf(data:Object,(k,v)->bool) -> self



-innerJoin(table:String) -> self //添加SQL inner join语句
-leftJoin(table:String) -> self //添加SQL left join语句
-rightJoin(table:String) -> self //添加SQL right join语句
-on(code:String) -> self //添加SQL on语句
-onEq(col1:String, col2:String) -> self //添加SQL on == 语句

-groupBy(code:String) -> self //添加SQL group by语句
-having(code:String) -> self //添加SQL having语句

-orderBy(code:String) -> self //添加SQL order by语句
-orderByAsc(col:String) -> self //添加SQL order by .. ASC语句
-orderByDesc(col:String) -> self //添加SQL order by .. DESC语句
-andByAsc(col:String) -> self //添加SQL order by .. ASC语句
-andByDesc(col:String) -> self //添加SQL order by .. DESC语句

-limit(size:int) -> self //添加SQL 分页语句(已兼容不同数据库)
-limit(start:int, size:int) -> self //添加SQL 分页语句(已兼容不同数据库)

-paging(start:int, size:int) //与limt一样,提供不同的用语习惯
-top(size:int) //与limt一样,提供不同的用语习惯

-append(code:String,args:Object...) ->self //添加无限制代码 //可使用?,?...占位符( ?... 表示数组占位符)

//
// 执行相关
//
-insert() -> long //执行插入并返回自增值,使用set接口的数据
-insert(data:IDataItem) -> long //执行插入并返回自增值,使用data数据
-insert(dataBuilder:(d:DataItem)->{}) -> long //执行插入并返回自增值,使用dataBuilder构建的数据
-insertList(valuesList:List<DataItem>) -> void //执行批量合并插入,使用集合数据
-insertList(valuesList:Collection<T>,dataBuilder:(t,d:DataItem)->{}) -> void //执行批量合并插入,使用集合数据(由dataBuilder构建数据)

-insertBy(constraints:String)//使用set接口的数据,根据约束字段自动插入 // exists + insert 的结合体
-insertBy(data:IDataItem,constraints:String)//使用data的数据,根据约束字段自动插入 // exists + insert 的结合体


-update() ->int //执行更新并返回影响行数,使用set接口的数据
-update(data:IDataItem) ->int //执行更新并返回影响行数,使用set接口的数据
-update(dataBuilder:(d:DataItem)->{}) ->int //执行更新并返回影响行数,使用dataBuilder构建的数据

-upsertBy(constraints:String)//使用set接口的数据,根据约束字段自动插入或更新 // exists + update + insert 的结合体
-upsertBy(data:IDataItem,constraints:String)//使用data的数据,根据约束字段自动插入或更新 // exists + update + insert 的结合体

-delete() -> int //执行删除,并返回影响行数

-select(columns:String) -> IQuery //执行查询,并返回查询接口(有非富的数据获取方式)

-selectExists() -> boolean //执行查询,并返回存在情况
-selectCount() -> long //执行查询,并返回COUNT(*)值
-selectCount(code:String) -> long //执行查询,并返回COUNT(..) //count code 要自己手写
-selectValue(column:String)-> Object
-selectValue(column:String, def:T)-> T
-selectItem(columns:String,Class<T> clz)-> T
-selectList(columns:String,Class<T> clz)-> List<T>
-selectMap(columns:String)-> Map<String,Object>
-selectMapList(columns:String)-> List<Map<String,Object>>
-selectArray(column:String)-> List<Object>

//
// 控制相关
//
-log(isLog:boolean) -> self //标记是否记录日志
-usingNull(isUsing:boolean) //充许使用null插入或更新
-usingExpr(isUsing:boolean) //充许使用$表达式做为set值


//
// 事务相关
//
-tran(transaction:DbTran) -> self //使用外部事务
-tran() -> self //使用事务


//
// 缓存控制相关
//
-caching(service:ICacheService) //使用一个缓存服务
-usingCache(isCache:boolean) //是否使用缓存
-usingCache(seconds:int) //使用缓存时间(单位:秒)
-cacheTag(tag:String) //为缓存添加标签

db.call("process") -> new:DbProcedure

//
// 注:DbProcedure implements IQuery
//

//例1: 调用数据库存储过程
//db.call("user_get").set("_user_id",1).getMap();

//例2: 调用xml sql
//db.call("@webapp.demo.dso.db.user_get").set("user_id",1).getMap();

//例3: 调用有变量的 sql
//db.call("select * from user where user_id=@{user_id}").set("user_id",1).getMap();

//
// 变量设置相关
//
-set(name:String,value:Object) -> self  //设置变量
-setInc(name:String,value:long) -> self //设置自增变量
-setIf(condition:bool,name:String,value:Object) -> self
-setMap(data:Map<String,Object>) -> self    //设置变量(将map输入)
-setMapIf(data:Map<String,Object>,(k,v)->bool) -> self
-setEntity(data:Object) -> self     //设置变量(将实体输入)
-setEntityIf(data:Object,(k,v)->bool) -> self

//
// 执行相关
// 
-insert() -> long //执行插入(返回自增ID)
-update() -> int //执行更新(返回受影响数)
-delete() -> int //执行删除(返回受影响数)
-execute() -> int //执行命令(返回受影响数)

* 执行查询见 IQuery 接口


//
// 事务相关
//
-tran(transaction:DbTran) -> self //使用外部事务
-tran() -> self //使用事务


//
// 缓存控制相关
//
-caching(service:ICacheService) //使用一个缓存服务
-usingCache(isCache:boolean) //是否使用缓存
-usingCache(seconds:int) //使用缓存时间(单位:秒)
-cacheTag(tag:String) //为缓存添加标签

db.sql("code") -> new:DbQuery

//
// 注:DbQuery implements IQuery
//

//例:db.sql("select * from user_id=?",12).getMap();

//
// 执行相关
// 
-insert() -> long //执行插入(返回自增ID)
-update() -> int //执行更新(返回受影响数)
-delete() -> int //执行删除(返回受影响数)
-execute() -> int //执行命令(返回受影响数)

* 执行查询见 IQuery 接口


//
// 事务相关
//
-tran(transaction:DbTran) -> self //使用外部事务
-tran() -> self //使用事务


//
// 缓存控制相关
//
-caching(service:ICacheService) //使用一个缓存服务
-usingCache(isCache:boolean) //是否使用缓存
-usingCache(seconds:int) //使用缓存时间(单位:秒)
-cacheTag(tag:String) //为缓存添加标签

附:IQuery 接口

public interface IQuery extends ICacheController<IQuery> {
     long getCount() throws SQLException;
     Object getValue() throws SQLException;
     <T> T getValue(T def) throws SQLException;

     Variate getVariate() throws SQLException;
     Variate getVariate(Act2<CacheUsing,Variate> cacheCondition) throws SQLException;

     <T extends IBinder> T getItem(T model) throws SQLException;
     <T extends IBinder> T getItem(T model, Act2<CacheUsing, T> cacheCondition) throws SQLException;


     <T extends IBinder> List<T> getList(T model) throws SQLException;
     <T extends IBinder> List<T> getList(T model, Act2<CacheUsing, List<T>> cacheCondition) throws SQLException;

     <T> T getItem(Class<T> cls) throws SQLException;
     <T> T getItem(Class<T> cls,Act2<CacheUsing, T> cacheCondition) throws SQLException;

     <T> List<T> getList(Class<T> cls) throws SQLException;
     <T> List<T> getList(Class<T> cls,Act2<CacheUsing, List<T>> cacheCondition) throws SQLException;

     DataList getDataList() throws SQLException;
     DataList getDataList(Act2<CacheUsing, DataList> cacheCondition) throws SQLException;
     DataItem getDataItem() throws SQLException;
     DataItem getDataItem(Act2<CacheUsing, DataItem> cacheCondition) throws SQLException;

     List<Map<String,Object>> getMapList() throws SQLException;
     Map<String,Object> getMap() throws SQLException;

     <T> List<T> getArray(String column) throws SQLException;
     <T> List<T> getArray(int columnIndex) throws SQLException;
}

附:BaseMapper 接口

public interface BaseMapper<T> {
    Long insert(T entity, boolean excludeNull);
    void insertList(List<T> list);

    Integer deleteById(Object id);
    Integer deleteByIds(Iterable idList);
    Integer deleteByMap(Map<String, Object> columnMap);
    Integer delete(Act1<MapperWhereQ> condition);

    /**
     * @param excludeNull 排除null
     * */
    Integer updateById(T entity, boolean excludeNull);
    Integer update(T entity, boolean excludeNull, Act1<MapperWhereQ> condition);

    int[] updateList(List<T> list, Act2<T,DataItem> dataBuilder, Property<T, ?>... conditionFields);

    Long upsert(T entity, boolean excludeNull);
    Long upsertBy(T entity, boolean excludeNull, String conditionFields);

    boolean existsById(Object id);
    boolean exists(Act1<MapperWhereQ> condition);

    T selectById(Object id);
    List<T> selectByIds(Iterable idList);
    List<T> selectByMap(Map<String, Object> columnMap);

    T selectItem(T entity);
    T selectItem(Act1<MapperWhereQ> condition);
    Map<String, Object> selectMap(Act1<MapperWhereQ> condition);

    Object selectValue(String column, Act1<MapperWhereQ> condition);

    Long selectCount(Act1<MapperWhereQ> condition);

    List<T> selectList(Act1<MapperWhereQ> condition);
    List<Map<String, Object>> selectMapList(Act1<MapperWhereQ> condition);
    List<Object> selectArray(String column, Act1<MapperWhereQ> condition);

    List<T> selectList(int start, int size, Act1<MapperWhereQ> condition);
    List<Map<String, Object>> selectMapList(int start, int size, Act1<MapperWhereQ> condition);
    List<Object> selectArray(String column, int start, int size, Act1<MapperWhereQ> condition);

    /**
     * @param start 从0开始
     * */
    IPage<T> selectPage(int start, int size, Act1<MapperWhereQ> condition);
    IPage<Map<String, Object>> selectMapPage(int start, int size, Act1<MapperWhereQ> condition);

    List<T> selectTop(int size, Act1<MapperWhereQ> condition);
    List<Map<String, Object>> selectMapTop(int size, Act1<MapperWhereQ> condition);
}

Wood mapper xml sql 语法

语法说明

mapper 开始标签
  namespace (属性:命名空间,{namespace}.{id} = sqlid;不包括文件名)
  import(属性:导入包或类,多个以;号隔开。可以简化后面的模型写法,或引入工具类)
  baseMapper(属性:扩展BaseMapper 的模型,效果:BaseMapper<Xxx>)
  db(属性:关联 dataSource bean;效果:@Db("xxx"))

sql 代码块定义指令
  id
  param?(属性:外部输入变量申明;默认会自动生成)
  declare?(属性:内部变量类型预申明)
  return(属性:返回类型)

  remarks(属性:描述、摘要)

  caching?(属性:缓存服务name) //是对 ICacheController 接口的映射
  cacheClear?(属性:清除缓存)
  cacheTag?(属性:缓存标签,支持在入参或结果里取值替换)
  usingCache?(属性:缓存时间,int)

if 判断控制指令(没有else)
  test (属性:判断检测代码)
     //xml避免语法增强:
     //lt(<) lte(<=) gt(>) gte(>=) and(&&) or(||)
        //例:m.sex gte 12 :: m.sex >=12
     //简化语法增强:
     //??(非null,var!=null) ?!(非空字符串, Utils.isNoteEmpty(var))
        //例:m.icon??  ::m.icon!=null
        //例:m.icon?!  ::Utils.isNoteEmpty(m.icon)

for 循环控制指令 (通过 ${var}_index 可获得序号,例:m_index)
  var (属性:循环变量申明)
  items (属性:集合变量名称)
  sep? (属性:分隔符)

trim 修剪指令
  trimStart(属性:开始位去除)
  trimEnd(属性:结尾位去除)
  prefix(属性:添加前缀)
  suffix(属性:添加后缀)

ref 引用代码块指令
  sql (属性:代码块id)

name:type    = 变量申明(可用于属性::param, :declare,var,或宏定义 @{..},${..})
@{name:type?} = 变量注入
${name:type?} = 变量替换,即成为字符串的一部份

//列表([]替代<>)
return="List[wooddemo.mapper.UserModel]" => List<UserModel>
return="List[String]" => List<String> (Date,Long,...大写开头的单值类型)
return="MapList" => List<Map<String,Object>>
return="DataList" => DataList

//一行
return="wooddemo.mapper.UserModel" => UserModel
return="Map" => Map<String,Object>
return="DataItem" => DataItem

//单值
return="String" => String (任何单职类型)

示例

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//noear.org//DTD Mapper 3.0//EN" "http://noear.org/dtd/wood-mapper.dtd">
<mapper namespace="wood_demo.xmlsql2"
        import="wood_demo.mapper.*"
        baseMapper="UserModel"
        db="testdb">
    <sql id="user_add1"
         return="long"
         param="m:UserModel,sex:int"
         remarks="添加用户">
        INSERT user(user_id,mobile,sex) VALUES(@{m.user_id},@{m.mobile},@{sex})
    </sql>

    <sql id="user_add2" return="long" remarks="添加用户">
        INSERT user(user_id) VALUES(@{user_id:int})
    </sql>

    <sql id="user_add_for" return="long" declare="list:List[UserModel]" remarks="批量添加用户3">
        INSERT user(id,mobile,sex) VALUES
        <for var="m:UserModel" items="list">
            (@{m.user_id},@{m.mobile},@{m.sex})
        </for>
    </sql>

    <sql id="user_del" remarks="删除一个用户">
        DELETE FROM user WHERE id=@{user_id:long}
        <if test="sex gt 0">
            AND sex=@{sex:int}
        </if>
    </sql>

    <sql id="user_set"
         remarks="更新一个用户,并清理相关相存"
         caching="localCache"
         cacheClear="user_${user_id},user_1">
        UPDATE user SET mobile=@{mobile:String},sex=@{sex:int}
        <if test="icon != null">
            icon=@{icon:String}
        </if>
    </sql>

    <sql id="user_get" remarks="获取用户" return="UserModel">
        SELECT * FROM user WHERE user_id=@{user_id:long}
    </sql>

    <sql id="user_get_list"
         remarks="获取一批符合条件的用户"
         declare="foList:int,user_id:long"
         return="List[UserModel]"
         caching="localCache"
         cacheTag="user_${user_id},user_1">
        SELECT id,${cols:String} FROM user
        <trim prefix="WHERE" trimStart="AND ">
            <if test="mobile?!">
                AND mobile LIKE '${mobile:String}%'
            </if>
            <if test="foList == 0">
                AND type='article'
            </if>
            <if test="foList == 1">
                AND type='post'
            </if>
        </trim>
    </sql>

    <sql id="user_cols1">name,title,style,label</sql>
    <sql id="user_cols2">name,title</sql>

    <sql id="user_get_list2"
         remarks="获取一批符合条件的用户"
         declare="foList:int,user_id:long"
         return="List[UserModel]"
         caching="localCache"
         cacheTag="user_${user_id},user_1">
        SELECT id,
        <if test="foList == 0">
            <ref sql="user_cols1"/>
        </if>
        <if test="foList == 1">
            <ref sql="user_cols2"/>
        </if>
        <![CDATA[
        FROM user WHERE sex > 1 AND mobile LIKE '@{mobile:String}%'
        ]]>
    </sql>

    <sql id="user_get_list3"
         remarks="获取一批符合条件的用户"
         return="List[UserModel]">
        SELECT * FROM user WHERE user_id IN (@{user_ids:List[Long]})
    </sql>
</mapper>

示例应用

//使用方案1
db.call("@wooddemo.xmlsql2.user_set").set("user_id",12).update()
db.call("@wooddemo.xmlsql2.user_add").setMap(map).insert()

//使用方案2
@Namespace("wooddemo.xmlsql2")
public interface UserDao extends BaseMapper<UserModel> {
    UserModel user_get(int user_id);
}

UserDao userDao = db.mapper(UserDao.class);
UserModel user = userDao.user_get(12);

//使用方案3
UserModel user = db.mapper("@wooddemo.xmlsql2.user_get", map);

项目地址:

https://github.com/noear/wood/

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表