TMapper的淘宝的win10激活码?

在spring中使用通用Mapper,抽象出通用的业务类BaseService&T&
前面已经介绍了如何使用通用Mapper(),
这里写一下Spring中使用Mapper的方案,这也是项目中的最优方案;
由于spring4增加了对泛型注入的支持,这个特性对于Mybatis的通用Mapper来说,非常的有用,可以直接在service中写Mapper&T&,通过BaseService&T& 来实现通用的Service;
Spring 抽象出Service方法– BaseService
public abstract class BaseService&T& {
@Autowired
private Mapper&T&
* 根据id查询数据
public T queryById(Long id) {
return mapper.selectByPrimaryKey(id);
* 查询所有数据
public List&T& queryAll() {
return mapper.select(null);
* 根据条件查询一条数据,如果有多条数据会抛出异常
public T queryOne(T record) {
return mapper.selectOne(record);
* 根据条件查询数据列表
public List&T& queryListByWhere(T record) {
return mapper.select(record);
* 分页查询
public PageInfo&T& queryPageListByWhere(Integer page, Integer rows, T record) {
PageHelper.startPage(page, rows);
List&T& list = this.queryListByWhere(record);
return new PageInfo&T&(list);
* 新增数据,返回成功的条数
public Integer save(T record) {
record.setCreated(new Date());
record.setUpdated(record.getCreated());
return mapper.insert(record);
* 新增数据,使用不为null的字段,返回成功的条数
public Integer saveSelective(T record) {
record.setCreated(new Date());
record.setUpdated(record.getCreated());
return mapper.insertSelective(record);
* 修改数据,返回成功的条数
public Integer update(T record) {
return mapper.updateByPrimaryKey(record);
* 修改数据,使用不为null的字段,返回成功的条数
public Integer updateSelective(T record) {
record.setUpdated(new Date());
return mapper.updateByPrimaryKeySelective(record);
* 根据id删除数据
public Integer deleteById(Long id) {
record.setUpdated(new Date());
return mapper.deleteByPrimaryKey(id);
* 批量删除
public Integer deleteByIds(Class&T& clazz, String property, List&Object& values) {
Example example = new Example(clazz);
example.createCriteria().andIn(property, values);
return mapper.deleteByExample(example);
* 根据条件做删除
public Integer deleteByWhere(T record) {
return mapper.delete(record);
用ItemCartService继承BaseService来实现业务需求:
public class ItemCartService extends BaseService&ItemCart&{
接下来看如何在Controller中调用Service:
@Autowired
ItemCartService itemCartS
@RequestMapping(method=RequestMethod.GET)
public ResponseEntity&List&ItemCart&& queryItemCart(@RequestParam(value="id" ,defaultValue="0")
Long parentId) {
ItemCart record=new ItemCart();
record.setParentId(parentId);
List&ItemCart& itemCarts=itemCartService.queryListByWhere(record);
if(itemCarts == null || itemCarts.isEmpty()){
return ResponseEntity.status(HttpStatus.Not_FOUND).body(null);
return ResponseEntity.ok(itemCarts);
}catch(Exception e){
e.printStackTrace();
return ResponseEntity.staus(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!没事看看 - MyBatis工具
如何开发自己的通用Mapper
自从发了通用Mapper-0.1.0版本后,我觉得对少数人来说,这可能是他们正好需要的一个工具。至少目前的通用DAO中,很少能有比这个更强大的。
但是对另一部分人来说,使用Mybatis代码生成器(我正在和一些朋友翻译这个文档,地址:)生成xml很方便,不需要使用通用Mapper。
实际上如果你无法在自己的业务中提取出通用的单表(多表实际上能实现,但是限制会增多,不如手写xml)操作,通用的Mapper除了能增加你的初始效率以及更干净的xml配置外,没有特别大的优势。
为了更方便的扩展通用Mapper,我对0.1.0版本进行了重构。目前已经发布了0.2.0版本,这里要讲如何开发自己需要的通用Mapper。
如何开发自己的通用Mapper
自己定义的通用Mapper必须包含泛型,例如MysqlMapper&T&。
自定义的通用Mapper接口中的方法需要有合适的注解。具体可以参考
需要继承来实现具体的操作方法。
通用Mapper中的Provider一类的注解只能使用相同的type类型(这个类型就是第三个要实现的类。)。实际上method也都写的一样。
HsqldbMapper实例
第一步,创建HsqldbMapper&T&
public interface HsqldbMapper&T& {
这个接口就是我们定义的通用Mapper,具体的接口方法在**第三步**写。其他的Mapper可以继承这个HsqldbMapper&T&。
第二部,创建HsqldbProvider
public class HsqldbProvider extends MapperTemplate {
//继承父类的方法
public HsqldbProvider(Class&?& mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
这个类是实际处理操作的类,需要继承MapperTemplate,具体代码在**第四步**写。
第三步,在HsqldbMapper&T&中添加通用方法
这里以一个分页查询作为例子。 public interface HsqldbMapper { /** * 单表分页查询 * * @param object * @param offset * @param limit *
@SelectProvider(type=HsqldbProvider.class,method = "dynamicSQL") List selectPage(@Param("entity") T object, @Param("offset") int offset, @Param("limit") int limit); }
返回结果为List,入参分别为查询条件和分页参数。在Mapper的接口方法中,当有多个入参的时候建议增加@Param注解,否则就得用param1,param2...来引用参数。
同时必须在方法上添加注解。查询使用SelectProvider,插入使用@InsertProvider,更新使用UpdateProvider,删除使用DeleteProvider。不同的Provider就相当于xml中不同的节点,如&select&,&insert&,&update&,&delete&。
因为这里是查询,所以要设置为SelectProvider,这4个Provider中的参数都一样,只有type和method。
type必须设置为实际执行方法的HasqldbProvider.class,method必须设置为"dynamicSQL"。
通用Mapper处理的时候会根据type反射HasqldbProvider查找方法,而Mybatis的处理机制要求method必须是type类中只有一个入参,且返回值为String的方法。"dynamicSQL"方法定义在MapperTemplate中,该方法如下:
public String dynamicSQL(Object record) {
return "dynamicSQL";
这个方法只是为了满足Mybatis的要求,没有任何实际的作用。
第四步,在HsqldbProvider中实现真正处理Sql的方法
在这里有一点要求,那就是HsqldbProvider处理HsqldbMapper&T&中的方法时,方法名必须一样,因为这里需要通过反射来获取对应的方法,方法名一致一方面是为了减少开发人员的配置,另一方面和接口对应看起来更清晰。
除了方法名必须一样外,入参必须是MappedStatement
ms,除此之外返回值可以是void或者SqlNode之一。
这里先讲一下通用Mapper的实现原理。通用Mapper目前是通过拦截器在通用方法第一次执行的时候去修改MappedStatement对象的SqlSource属性。而且只会执行一次,以后就和正常的方法没有任何区别。
使用Provider注解的这个Mapper方法,Mybatis本身会处理成ProviderSqlSource(一个SqlSource的实现类),由于之前的配置,这个ProviderSqlSource种的SQL是上面代码中返回的"dynamicSQL"。这个SQL没有任何作用,如果不做任何修改,执行这个代码肯定会出错。所以在拦截器中拦截符合要求的接口方法,遇到ProviderSqlSource就通过反射调用如HsqldbProvider中的具体代码去修改原有的SqlSource。
最简单的处理Mybatis SQL的方法是什么?就是创建SqlNode,使用DynamicSqlSource,这种情况下我们不需要处理入参,不需要处理代码中的各种类型的参数映射。比执行SQL的方式容易很多。
有关这部分的内容建议查看通用Mapper的源码和Mybatis源码了解,如果不了解在这儿说多了反而会乱。
下面在HsqldbProvider中添加public
SqlNode selectPage(MappedStatement ms)方法:
* 分页查询
* @param ms
public SqlNode selectPage(MappedStatement ms) {
Class&?& entityClass = getSelectReturnType(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
List&SqlNode& sqlNodes = new ArrayList&SqlNode&();
//静态的sql部分:select column ... from table
sqlNodes.add(new StaticTextSqlNode("SELECT "
+ EntityHelper.getSelectColumns(entityClass)
+ " FROM "
+ tableName(entityClass)));
//获取全部列
List&EntityHelper.EntityColumn& columnList = EntityHelper.getColumns(entityClass);
List&SqlNode& ifNodes = new ArrayList&SqlNode&();
boolean first =
//对所有列循环,生成&if test="property!=null"&[AND] column = #{property}&/if&
for (EntityHelper.EntityColumn column : columnList) {
StaticTextSqlNode columnNode
= new StaticTextSqlNode((first ? "" : " AND ") + column.getColumn()
+ " = #{entity." + column.getProperty() + "} ");
if (column.getJavaType().equals(String.class)) {
ifNodes.add(new IfSqlNode(columnNode, "entity."+column.getProperty()
+ " != null and " + "entity."+column.getProperty() + " != '' "));
ifNodes.add(new IfSqlNode(columnNode, "entity."+column.getProperty() + " != null "));
//将if添加到&where&
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), new MixedSqlNode(ifNodes)));
//处理分页
sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit}"),"offset==0"));
sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit} OFFSET #{offset} "),"offset&0"));
return new MixedSqlNode(sqlNodes);
注:对这段代码感觉吃力的,可以对比本页最下面**结构**部分XML形式的查看。
首先这段代码要实现的功能是这样,根据传入的实体类参数中不等于null(字符串也不等于'')的属性作为查询条件进行查询,根据分页参数进行分页。
先看这两行代码:
//获取实体类型
Class&?& entityClass = getSelectReturnType(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
首先获取了实体类型,然后通过setResultType将返回值类型改为entityClass,就相当于resultType=entityClass。
这里为什么要修改呢?因为默认返回值是T,Java并不会自动处理成我们的实体类,默认情况下是Object,对于所有的查询来说,我们都需要手动设置返回值类型。
对于insert,update,delete来说,这些操作的返回值都是int,所以不需要修改返回结果类型。
之后从List&SqlNode&
sqlNodes = new ArrayList&SqlNode&();代码开始拼写SQL,首先是SELECT查询头,在EntityHelper.getSelectColumns(entityClass)中还处理了别名的情况。
然后获取所有的列,对列循环创建&if
entity.property!=null&column = #{entity.property}&/if&节点。最后把这些if节点组成的List放到一个&where&节点中。
这一段使用属性时用的是 entity.
+ 属性名,entity来自哪儿?来自我们前面接口定义处的Param("entity")注解,后面的两个分页参数也是。如果你用过Mybatis,相信你能明白。
之后在&where&节点后添加分页参数,当offset==0时和offset&0时的分页代码不同。
最后封装成一个MixedSqlNode返回。
返回后通用Mapper是怎么处理的,这里贴下源码:
SqlNode sqlNode = (SqlNode) method.invoke(this, ms);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode);
setSqlSource(ms, dynamicSqlSource);
返回SqlNode后创建了DynamicSqlSource,然后修改了ms原来的SqlSource。
第五步,配置通用Mapper接口到拦截器插件中
&plugin interceptor="com.github.abel533.mapper.MapperInterceptor"&
&!--================================================--&
&!--可配置参数说明(一般无需修改)--&
&!--================================================--&
&!--UUID生成策略--&
&!--配置UUID生成策略需要使用OGNL表达式--&
&!--默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")--&
&!--&property name="UUID" value="@java.util.UUID@randomUUID().toString()"/&--&
&!--主键自增回写方法,默认值MYSQL,详细说明请看文档--&
&property name="IDENTITY" value="HSQLDB"/&
&!--序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle--&
&!--可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName,PropertyName--&
&property name="seqFormat" value="{0}.nextval"/&
&!--主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)--&
&!--&property name="ORDER" value="AFTER"/&--&
&!--支持Map类型的实体类,自动将大写下划线的Key转换为驼峰式--&
&!--这个处理使得通用Mapper可以支持Map类型的实体(实体中的字段必须按常规方式定义,否则无法反射获得列)--&
&property name="cameHumpMap" value="true"/&
&!--通用Mapper接口,多个用逗号隔开--&
&property name="mappers" value="com.github.abel533.mapper.Mapper,com.github.abel533.hsqldb.HsqldbMapper"/&
&/plugins&
这里主要是**mappers**参数:
&property name="mappers" value="com.github.abel533.mapper.Mapper,com.github.abel533.hsqldb.HsqldbMapper"/&
多个通用Mapper可以用逗号隔开。
接下来编写代码进行测试。
public interface CountryMapper extends Mapper&Country&,HsqldbMapper&Country& {
在CountryMapper上增加继承HsqldbMapper&Country&。
编写如下的测试:
public void testDynamicSelectPage() {
SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
//带查询条件的分页查询
Country country = new Country();
country.setCountrycode("US");
List&Country& countryList = mapper.selectPage(country, 0, 10);
//查询总数
Assert.assertEquals(1, countryList.size());
//空参数的查询
countryList = mapper.selectPage(new Country(), 100, 10);
Assert.assertEquals(10, countryList.size());
} finally {
sqlSession.close();
测试输出日志如下:
DEBUG [main] - ==&
Preparing: SELECT ID,COUNTRYNAME,COUNTRYCODE FROM COUNTRY WHERE COUNTRYCODE = ? LIMIT ?
DEBUG [main] - ==& Parameters: US(String), 10(Integer)
TRACE [main] - &==
Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE [main] - &==
Row: 174, United States of America, US
DEBUG [main] - &==
DEBUG [main] - ==&
Preparing: SELECT ID,COUNTRYNAME,COUNTRYCODE FROM COUNTRY LIMIT ? OFFSET ?
DEBUG [main] - ==& Parameters: 10(Integer), 100(Integer)
TRACE [main] - &==
Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE [main] - &==
Row: 101, Maldives, MV
TRACE [main] - &==
Row: 102, Mali, ML
TRACE [main] - &==
Row: 103, Malta, MT
TRACE [main] - &==
Row: 104, Mauritius, MU
TRACE [main] - &==
Row: 105, Mexico, MX
TRACE [main] - &==
Row: 106, Moldova, Republic of, MD
TRACE [main] - &==
Row: 107, Monaco, MC
TRACE [main] - &==
Row: 108, Mongolia, MN
TRACE [main] - &==
Row: 109, Montserrat Is, MS
TRACE [main] - &==
Row: 110, Morocco, MA
DEBUG [main] - &==
测试没有任何问题。
这里在来点很容易实现的一个功能。上面代码中:
countryList = mapper.selectPage(new Country(), 100, 10);
传入一个没有设置任何属性的Country的时候会查询全部结果。有些人会觉得传入一个空的对象不如传入一个null。我们修改测试代码看看结果。
执行测试代码后抛出异常:
Caused by: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, "id")
为什么会异常呢,因为我们上面代码中直接引用的entity.property,在引用前并没有判断entity
!= null,因而导致了这里的问题。
我们修改HsqldbProvider中的selectPage方法,将最后几行代码进行修改,原来的代码:
//将if添加到&where&
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), new MixedSqlNode(ifNodes)));
//增加entity!=null判断
IfSqlNode ifSqlNode = new IfSqlNode(new MixedSqlNode(ifNodes),"entity!=null");
//将if添加到&where&
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), ifSqlNode));
之后再进行测试就没有问题了。
更多例子可以参考通用Mapper中的Mapper&T&和MapperProvider进行参考。代码量不是很大但是实现了常用的这些功能。
当你了解了原理以及掌握了SqlNode的结构后,相信你能写出更多更强大的通用Mapper。
我曾经说过会根据不同的数据库写一些针对性的通用Mapper,当我开始考虑重构的时候,我就想,我应该教会需要这个插件的开发人员如何自己实现。
一个人的能力是有限的,而且写一个东西开源出来给大家用很容易,但是维护不易。所以呢,我希望觉得这篇文档有用的各位能够分享自己的实现。
我个人如果有时间,我会考虑增加通用的Example查询。Example类的设计比较复杂,对应的SqlNode结构并不是很复杂。如果有人有兴趣,我可以协助开发Example通用查询。
对于刚刚了解上述内容的开发人员来说,SqlNode可能没有那么直观,为了便于理解。我在这里将上面最后修改完成的SqlNode以xml的形式写出来。
&select id="selectPage" resultType="com.github.abel533.model.Country"&
SELECT ID,COUNTRYNAME,COUNTRYCODE FROM COUNTRY
&if test="entity!=null&
&if test="entity.id!=null"&
id = #{entity.id}
&if test="entity.countryname!=null"&
countryname = #{entity.countryname}
&if test="entity.countrycode!=null"&
countrycode = #{entity.countrycode}
&if test="offset==0"&
LIMIT #{limit}
&if test="offset&0"&
LIMIT #{limit} OFFSET #{offset}
看到这个结构,再和上面代码一一对应应该就不难理解了。熟悉以后,你可能也会觉得JAVA代码方式处理通用的Mapper会容易很多。
扫码向博主提问
MyBatis相关答疑
擅长领域:
Spring Boo
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!TMapper下载_TMapper安卓版apk下载-优亿市场
请输入6-16位密码
1.01亿次 下载
下载数:小于50次
下载数:200次
下载数:200次
下载数:200次
下载数:200次
下载数:200次
下载数:200次
下载数:200次
下载数:200次
获取验证码
恭喜你,密码重置成功
用户客服QQ:
开发者反馈QQ:
客服邮箱:
举报电话:
商务合作QQ:
资讯投稿:
(C) www.eoemarket.com 版权所有 北京浩游网讯科技有限公司
感谢使用优亿市场,恳请您提出宝贵的建议,被采纳的建议均可获得30元话费充值卡。
请输入您的意见建议,万分感谢!
联系方式(可选)
加群抢红包!使用PP助手
下载Tmapper的还喜欢下载
PP助手为您下载提速
阿里巴巴旗下手机助手Tmapper安卓版手持GPS软件,手持GPS的颠覆者!简单易用:软件功能一目了然,操作习惯完全与手持机功能相同,只要拥有一部带GPS的安卓手机 即可马上体验;地图:采用在线+离线地图方式工作,在线地图支持Google和百度地图,也可使用在线地图离线包 数据,支持shp数据;照片导航:实现坐标数据与照片组合,使用照片直接导航;坐标转换:内置多种投影转换方式,84转54等,支持国内常见坐标系统,自由变换;面积测量:单独的面积计算功能,帮您简单、方便、精准的计算面积;数据记录:具备航点、航线、航迹采集、编辑、导航等功能;输出格式:多种GIS数据输出格式,能满足所有数据处理要求;
手机扫描二维码下载
大家都在玩
大小:35.05MB
Tmapper安卓版手持GPS软件,手持GPS的颠覆者!简单易用:软件功能一目了然,操作习...
大小:35.05MB
Tmapper安卓版手持GPS软件,手持GPS的颠覆者!简单易用:软件功能一目了然,操作习...
大家都在玩
热门安卓应用
WiFi万能钥匙
百度输入法
搜狗输入法
其他用户正在浏览
猪猪保卫战
蘑菇园 官方中文版}

我要回帖

更多关于 迷你世界的最新激活码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信