代码地址以下:
http://www.demodashi.com/demo/12468.htmlhtml
众所周知,mybatis 虽然易于上手,但放到互联网环境下使用时,不可避免的要面对诸如‘’一级缓存存在脏数据‘’、‘’须要写大量明文 SQL 语句‘’等问题。对于这些问题 mybatis 的开发团队选择了一种谦逊的方式,他们开放 mybatis 接口,容许用户开发插件,按本身的方式来解决这些问题。因而,一切 ORM 领域相关的问题在 mybatis 上经过插件都有了解决方案。java
之前咱们在 mapper.xml 中要写很复杂的 sql 语句,但如今在 mapper.xml 中只需这样:git
<select id="select" resultMap="result"> flying#{?}:select </select> <select id="selectOne" resultMap="result"> flying:selectOne </select> <insert id="insert"> flying:insert </insert> <update id="update"> flying:update </update> <delete id="delete"> flying:delete </delete>
再在您的实体类上加上这样一些标注:github
package myPackage; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; @Table(name = "account") public class Account { @Id @Column private Integer id; @Column private java.lang.String name; @Column private Integer age; /* 省略 getter 和 setter */ }
flying 就彻底明白您的数据结构和您想作的事情了。 接下来您增删改查这个实体就会变得很是简单:web
/* 新增 */ Account newAccount = new Account(); newAccount.setName("ann"); newAccount.setAge(18); accountService.insert(newAccount); /* 按主键查询 */ Account account = accountService.select(newAccount.getId()); /* 按姓名查询,这里忽略了年龄 */ Account accountC1 = new Account(); accountC1.setName("ann"); Account account1 = accountService.selectOne(accountC1); /* account1 和 account 表明相同的业务数据 */ /* 按年龄查询,这里忽略了姓名 */ Account accountC2 = new Account(); accountC2.setAge(18); Account account2 = accountService.selectOne(accountC2); /* account2 和 account 表明相同的业务数据 */ /* 按姓名和年龄查询 */ Account accountC3 = new Account(); accountC3.setName("ann"); accountC3.setAge(18); Account account3 = accountService.selectOne(accountC3); /* account3 和 account 表明相同的业务数据 */ /* 修改 */ account.setName("bob"); accountService.update(newAccount); /* 按主键删除 */ accountService.delete(newAccount);
因为 flying 掌握了您所有的数据结构和实体关系,因此操做数据变得很是简单,您不再须要定义 “getAccountById、getAccountByName、getAccountByAge” 这样重复性强的方法了,由此带来更大的好处是您的 service 层只须要关注事务方面的逻辑便可,它从低级代码中彻底解放了出来。以上只是 flying 功能的冰山一角,其它的功能如多表联查、分页、乐观锁、跨数据源查询、二级缓存等 flying 都有简单的解决方案,您能够在 flying-doc.limeng32.com 中进行查看。redis
flying 特色总结以下:算法
数据操做入参和返回类型都是自定义的实体类,彻底 no sql 杜绝各类‘’手滑‘’,项目可随意重构。sql
支持跨表操做和跨数据源操做。apache
非侵占工做机制,能够和您已有的 mybatis 方法协同工做。后端
加入了优化过的缓存插件,能够对多数据源环境下 flying 方法和传统 mybatis 方法同时进行缓存管理。
能够自定义主键生成器,全面支持或逻辑查询。(初雪版新增特性)
flying 的 maven 坐标为:
<groupId>com.github.limeng32</groupId> <artifactId>mybatis.flying</artifactId> <version>0.9.3</version>
mybatis 版本与 flying 最新版本初雪的对应关系见下:
mybatis 版本 | flying-初雪 |
---|---|
3.3.0、3.3.1 | 0.8.3 |
3.4.0、3.4.一、3.4.二、3.4.三、3.4.四、3.4.5 | 0.9.3 |
之因此采用分版本发布的方式是由于咱们对 mybatis 每一个版本的用户都认真负责,力求使您获得 flying 最大的好处。
一、将代码搭建成 maven 项目。
二、以 maven 命令执行 tomcat7:run
如下是初始化时的添加的数据源 dataSource 和 dataSource2,将商品业务数据和用户数据分开存放是一种常见作法。dataSource 描述了两个购物车和 12 种商品和商品装入购物车的状况:
<dataset> <CART ID="1" DEAL="0" DEAL_TIME=null PERSON_ID="1"/> <CART ID="2" DEAL="0" DEAL_TIME=null PERSON_ID="2" /> <COMMODITY ID="1" NAME="牙刷A" PRICE="1200" /> <COMMODITY ID="2" NAME="牙刷B" PRICE="1850" /> <COMMODITY ID="3" NAME="牙刷C" PRICE="2100" /> <COMMODITY ID="4" NAME="佳洁士牙膏" PRICE="1499" /> <COMMODITY ID="5" NAME="六必治牙膏" PRICE="1999" /> <COMMODITY ID="6" NAME="云南白药牙膏" PRICE="2499" /> <COMMODITY ID="7" NAME="潘婷洗发露" PRICE="3500" /> <COMMODITY ID="8" NAME="多芬洗发露" PRICE="3900" /> <COMMODITY ID="9" NAME="海飞丝洗发露" PRICE="5100" /> <COMMODITY ID="10" NAME="浴液-1500ML" PRICE="2800" /> <COMMODITY ID="11" NAME="浴液-2000ML" PRICE="3200" /> <COMMODITY ID="12" NAME="浴液-4000ML" PRICE="4900" /> <CART_COMMODITY ID="1" CART_ID="1" COMM_ID="1" AMOUNT="3" /> <CART_COMMODITY ID="2" CART_ID="1" COMM_ID="5" AMOUNT="4" /> <CART_COMMODITY ID="3" CART_ID="1" COMM_ID="8" AMOUNT="1" /> <CART_COMMODITY ID="4" CART_ID="1" COMM_ID="12" AMOUNT="1" /> <CART_COMMODITY ID="5" CART_ID="2" COMM_ID="2" AMOUNT="2" /> <CART_COMMODITY ID="6" CART_ID="2" COMM_ID="4" AMOUNT="1" /> <CART_COMMODITY ID="7" CART_ID="2" COMM_ID="9" AMOUNT="2" /> <CART_COMMODITY ID="8" CART_ID="2" COMM_ID="11" AMOUNT="1" /> </dataset>
dataSource2 描述了 3 种会员级别和 3 位用户的状况:
<dataset> <ROLE ID="1" NAME="普通会员" VALUE="normal" /> <ROLE ID="2" NAME="银牌会员" VALUE="silver" /> <ROLE ID="3" NAME="金牌会员" VALUE="gold" /> <PERSON ID="1" NAME="张三" ROLE_ID="1" /> <PERSON ID="2" NAME="李四" ROLE_ID="2" /> <PERSON ID="3" NAME="王五" ROLE_ID="3" /> </dataset>
运行起来后,具体的功能访问页面能够用以下方式访问到,在浏览器中输入如下 url 能够看到效果:
查看购物车: http://localhost:8080/flying-demo2/getCart?id=${购物车cart的id}
查看商品: http://localhost:8080/flying-demo2/getCommodity?id=${商品commodity的id}
翻页查看商品(全部条件均为可选): http://localhost:8080/flying-demo2/getCommodityInPage?pageNum=${页码}&priceOrder=${按价格升序或降序输入asc或desc}&priceFrom=${价格最小值}&priceTo=${价格最大值}
增长新商品: http://localhost:8080/flying-demo2/addCommodity?name=${新商品名称}&price=${新商品价格}
编辑商品: http://localhost:8080/flying-demo2/updateCommodity?id=${商品的id}&name=${商品的名称}&price=${商品的价格}
查看购物车中的商品: http://localhost:8080/flying-demo2/getCommodityByCart?id=${购物车的id}
对购物车进行结帐: http://localhost:8080/flying-demo2/dealCart?id=${购物车的id}
取消购物车的结帐: http://localhost:8080/flying-demo2/undealCart?id=${购物车的id}
查看用户: http://localhost:8080/flying-demo2/getPerson?id=${用户的id}
查看会员级别: http://localhost:8080/flying-demo2/getRole?id=${会员级别的id}
编辑会员级别: http://localhost:8080/flying-demo2/updateRoleDirectly?id=${会员级别的id}&name=${会员级别的名称}
查询匹配两个级别值(如gold、silver、normal)的会员级别(使用或逻辑特性):
http://localhost:8080/flying-demo2/getRoleValue1OrValue2?value1=${级别值1}&value2=${级别值2}
查询会员级别值(如gold、silver、normal)或用户名称匹配给定值的用户(使用外键或逻辑特性)
http://localhost:8080/flying-demo2/getRoleValueOrPersonName?value=${级别值}&name=${用户名称}
向当前购物车加入/删除商品(amount为负数时为删除),并自动处理最终结果(用来展现双向相关算法下处理业务模型的优雅)
http://localhost:8080/flying-demo2/addCommodityToCart?cartId=${购物车的id}&commId=${商品的id}&amount=${购买数量}
按两个用户id查询购买的商品详情(使用跨库或逻辑特性)
http://localhost:8080/flying-demo2/getCartCommodityByPersonId1OrId2?id1=${用户id1}&id2=${用户id2}
不刷新缓存的编辑会员级别:http://localhost:8080/flying-demo2/updateRoleDirectlyWithoutCache?id=${会员级别的id}&name=${会员级别的名称}
以上方法的实现代码可见: https://github.com/limeng32/flying-demo2/blob/use-flying-0.9.3/src/main/java/indi/demo/flying/web/CommonController.java
从 use-flying-0.9.3
分支开始咱们采用双向相关的方式构建 pojo,以求打造一个真实可用的电商前台,关于双向相关的详细信息请见: https://my.oschina.net/u/2280950/blog/1580056
以上API方法除最后一个外,其他均支持了二级缓存。您能够调用 updateRoleDirectlyWithoutCache
修改会员级别名称,以后调用 getRole
能看到新的名称,但调用 getCart
和 getCommodityByCart
则只能看到修改前的名称,这是由于 updateRoleDirectlyWithoutCache
设计为不支持二级缓存,从这里能够看出缓存确实发挥了做用;若是您调用 updateRoleDirectly
修改会员级别名称,在调用 getRole
、getCart
和 getCommodityByCart
都会显示出新的名称,由于 updateRoleDirectly
设计为支持二级缓存。若是再使用 redis 托管 mybatis 的二级缓存,就成为了可扩展的缓存解决方案,不过这已超过本例的讨论范围。
updateRoleDirectly
和 updateRoleDirectlyWithoutCache
都是普通 mybatis 方法而非 flying 自动映射方法,这个例子也说明改造 mybatis 二级缓存的插件可供 flying 自动映射方法和非 flying 自动映射方法同时工做。
最后,flying 项目介绍请见 flying-doc.limeng32.com ,咱们为开发最好的 mybatis 插件而努力。
使用 mybatis + flying + 双向相关建模 的电商后端
代码地址以下:
http://www.demodashi.com/demo/12468.html
注:本文著做权归做者,由demo大师代发,拒绝转载,转载须要做者受权