曾将发布过俩篇关于Mybatis封装的文章,当时曾曾承诺过当测试没有问题后阿海会整理一下然后将原代码发布出来。
那么今天正好朋友找我要一份那套mybatis封装的源码,我便整理了一份,想想这么长时间了并没有发现什么明显的bug,于是决定将它发出来。
喜欢的朋友可以在这里下载:
关于这个mybatis的封装,我且叫他CRUD框架吧,这样说着还顺口一点。这是一个Maven工程,代码在src/main/java中。配置文件在src/main/resource中,这就不多说了,整个CRUD的源码在com.aiyi.core包中。
喜欢的朋友可以进去瞅瞅,也没有什么高深的技术,就是写了一个公用的Dao并代理了一下dao的实现层。还有就是com.aiyi.base包中,就是你写代码的地方了,里面有一些dao包啦、service包啦、controller包啦之类的。这事我随便写的一些使用的例子,这些根据自己项目结构随便改。
接下来就是一些使用方式什么的,将工程导入到eclipse中后,进入com.aiyi.base.dao包,可以看到两个实体类,这两个实体类对应的是数据库中的两张表。
TestUserPo.java:
package com.aiyi.base.pojo;import com.aiyi.core.annotation.po.FieldName;
import com.aiyi.core.annotation.po.TableName;
import com.aiyi.core.annotation.po.TempField;
import com.aiyi.core.beans.Po;//@TableName 用来表示当前实体类对应数据库中的表名
@TableName(name="q_test_table1")
public class TestUserPo extends Po {private int id;
//@FieldName 注解是用来标识该字段对应的数据库字段名。假如数据库字段和实体类中的字段一致的话,就不需要这个注解
@FieldName(name="img_id")
private int imgId;
private String name;
//@TempField 注解标识 imgUrl 这个字段是一个临时字段,也就是说,在数据库中这个字段是不存在的。
@TempField
private String imgUrl;public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public int getImgId() {
return imgId;
}public void setImgId(int imgId) {
this.imgId = imgId;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public String getImgUrl() {
return imgUrl;
}public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
}
TestImgResourcePo.java:
package com.aiyi.base.pojo;import com.aiyi.core.annotation.po.TableName;
import com.aiyi.core.beans.Po;@TableName(name="q_test_table2")
public class TestImgResourcePo extends Po {private int id;
private String url;public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public String getUrl() {
return url;
}public void setUrl(String url) {
this.url = url;
}
}
com.aiyi.base.dao 包中,有资格类,分别是 UserDao、ImgResourceDao 以及他们的接口。这里如果你只是单纯的想用 CRUD 做开发的话,
一般情况下是不用写那两个接口类的,也就是说,你只需要写 UserDao、ImgResourceDao 这两个类就好了,但是这里既然是例子,那就说全一点,一般情况下虽然不需要写 dao 的接口类,但是我喜欢二班情况。
若问我为什么要闲着没事儿给他写接口玩儿,是因为我封装的这套 CRUD 支持编程扩展的。也就是说,你可以在开发的时候根据需要扩展他的功能。你可以理解为一种叫做“插件”的东西。待会儿我要在两张表内各插入 3000 条数据,原始的 CRUD 框架虽然可以插入数据,但是他只能一条一条的插入,虽然你可以写个可爱的 for 循环,但是效率摆在那,如果想批量的插入一些数据的话,你或许需要给他增加这么一个功能,也就是说,给他写一个支持批量增加记录的插件。
所以请看好,接下来的相信在实际开发中经常会遇到,我给他添加批量新增的支持,就先建立一个接口类并给他生命一个 add 方法用来批量添加数据:
package com.aiyi.base.dao;import java.util.List;
import com.aiyi.base.pojo.TestUserPo;
/**
* UserDao 的接口类,也属于爱易 CRUD 的插件扩展类。这个类一般情况下不用创建。当需要重载或者新增 REUD 框架的一些方法时,可以声明接口类
* 本接口类重载了 add()方法,使 add 方法可以一次性插入多条数据,极大的提高了数据批量增加的效率
* @author 郭胜凯
* @time 2016 年 6 月 28 日下午 12:51:29
* @email 719348277@qq.com
*
*/
public interface UserDaoInterface {int add(List list);
}
接口类建立了以后,我需要写一个 mapper 映射文件,将它执行的 sql 映射一下,那么我建立一个 com.aiyi.base.mapper.userDaoMapper.xml:
并将它的 namespace 指向咱们先前写的这个接口:com.aiyi.base.dao.UserDaoInterface
<mapper namespace="com.aiyi.base.dao.UserDaoInterface">
<insert id="user_addList" useGeneratedKeys="true" parameterType="java.util.List">
insert into q_test_table1 (img_id, name)
values
<foreach collection="list" item="item" index="index"
separator=",">
(#{item.imgId}, #{item.name})
接下来建立 UserDao.java,并继承 DaoImpl,DaoImpl 有两个泛型,第一个是当前 Dao 对应的实体类,第二个是当前实体类中的主键类型。这个时候,你的这个 UserDao 就已经拥有通用的增删改查方法了但是我希望他拥有批量新增的方法,所以我在让他实现之前的 UserDaoInterface 这个类。
package com.aiyi.base.dao;import java.util.List;
import javax.annotation.Resource;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;import com.aiyi.base.pojo.TestUserPo;
import com.aiyi.core.dao.impl.DaoImpl;/**
* UserDao 的实现类,该类继承了公共 Dao 的原始方法。当你要给爱易 REUD 框架增加新功能时,不用去改源码,爱易 CRUD 提供了可编程式插件接口的方案。
* 你可以编写一个接口类并实现他,以此来扩展爱易 CRUD
* @author 郭胜凯
* @time 2016 年 6 月 28 日下午 12:56:42
* @email 719348277@qq.com
*
*/
@Repository
public class UserDao extends DaoImpl<TestUserPo, Integer> implements UserDaoInterface /UserDaoInterface 这个接口是一个插件实现的演示。他完善了爱易 CRUD 的批量添加方案/ {@Resource
private SqlSessionTemplate sqlSessionTemplateASS;
/**
* 重载 Add 方法,批量添加
* @param list
* @return
*/
public int add(List list){
long startId = nextId();
for (int i = 0; i < list.size(); i++) {
list.get(i).setId(Integer.valueOf(startId + i + ""));
}
//注意了,这里的“user_addList”对应的是 userDaoMapper.xml 中的 insertSQL 块的 Id
return sqlSessionTemplateASS.insert("user_addList", list);
}
}
好了,这么一个批量新增的扩展类已经编写完成了!你只需要调用 userDao.add()方法的时候,传入一个 list 进去,他就会以最短的时间吧 list 中的元素插入到数据库中!
接下来吧 imgDao 页添加一个批量新增的功能,以上面一样,所以我就不再贴代码了!看我写个 Service 来测试一下!
package com.aiyi.base.service.impl;import java.util.ArrayList;
import java.util.List;import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;import com.aiyi.base.dao.ImgDao;
import com.aiyi.base.dao.UserDao;
import com.aiyi.base.pojo.TestImgResourcePo;
import com.aiyi.base.pojo.TestUserPo;
import com.aiyi.base.service.TestService;
import com.aiyi.core.beans.Method;
import com.aiyi.core.sql.where.C;
import com.aiyi.core.util.Formatter;
import com.aiyi.core.util.FormatterSql;@Service
public class TestServiceImpl implements TestService {
@Resource
private ImgDao imgDao;
@Resource
private UserDao userDao;//批量新增 User 和 Img 各 3000 条,速度嗖嗖的
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public int addList() {
// TODO Auto-generated method stub
List users = new ArrayList<>();
List imgs = new ArrayList<>();
for (int i = 0; i < 3000; i++) {
TestImgResourcePo imgResourcePo = new TestImgResourcePo();
imgResourcePo.setUrl("http://imgresource.com/url/" + i + ".jpg");
imgs.add(imgResourcePo);
}
int add = imgDao.add(imgs);
for (int i = 0; i < 3000; i++) {
TestUserPo testUserPo = new TestUserPo();
testUserPo.setImgId(imgs.get(i).getId());
testUserPo.setName("用户" + i);
users.add(testUserPo);
}
add += userDao.add(users);
return add;
}//联表查询,之前说了 user 实体类的 imgUrl 是一个临时字段,他的真正的值在 img 表的 url 字段里,user 中的 imgId 对应的就是 img 表中的 Id
@Override
public List listUser() {
// TODO Auto-generated method stub
Formatter fmt = new FormatterSql();
fmt.addFmt("imgUrl", "url", TestImgResourcePo.class, Method.where("[fmt.R].id", C.EQ, "[fmt.L].img_id"));
return userDao.listFormat(Method.createDefault(), fmt);
}
}
写个 Controller 跑一下:
package com.aiyi.base.controller;import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.aiyi.base.pojo.TestUserPo;
import com.aiyi.base.service.TestService;@Controller
public class TestController {@Resource
private TestService testService;
/**
* 添加测试
* @return
/
@RequestMapping("testAdd")
@ResponseBody
public Object testAddList(){
long t = System.currentTimeMillis();
int n = testService.addList();
long tT = System.currentTimeMillis();
double s = (tT - t) / 1000;
return "共添加" + n + "条数据,用时" + s + "秒";
}
/*
* 查询测试
* @return
/
@RequestMapping("testSelect")
@ResponseBody
public Object testSelectFmt(){
long t = System.currentTimeMillis();
List listUser = testService.listUser();
long tT = System.currentTimeMillis();
double s = (tT - t) / 1000;
Map<String, Object> map = new HashMap<>();
map.put("msg", "共查询" + listUser.size() + "条记录,用时" + s + "秒");
map.put("oData", listUser);
return map;
}
}
以上就是这个样子,更多的东西可以从我以前的文章中看到,或者自己下载源码摸索一下,这里就介绍这么多了至此,再见!
呃。。等等,还有个事儿给忘了,数据库在/crud2/src/main/resources/jdbc.properties 下面配置成自己的。
下面是 Mysql 的两张测试表:
/
Navicat MySQL Data TransferSource Server : aiyi_web
Source Server Version : 50518
Source Host : rm-bp1995mscsm3q9bus.mysql.rds.aliyuncs.com:3306
Source Database : rz4m1ulg3qTarget Server Type : MYSQL
Target Server Version : 50518
File Encoding : 65001Date: 2016-06-28 16:38:37
*/SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for q_test_table1
-- ----------------------------
DROP TABLE IF EXISTSq_test_table1
;
CREATE TABLEq_test_table1
(
id
int(11) NOT NULL AUTO_INCREMENT,
name
varchar(255) DEFAULT NULL,
img_id
int(11) DEFAULT NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=12001 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for q_test_table2
-- ----------------------------
DROP TABLE IF EXISTSq_test_table2
;
CREATE TABLEq_test_table2
(
id
int(11) NOT NULL AUTO_INCREMENT,
url
varchar(255) DEFAULT NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=21001 DEFAULT CHARSET=utf8;
OK!到此,真的再见了!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于