微型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/
本文暂时没有评论,来添加一个吧(●'◡'●)