基于mysql Jdbctemplate 的上层封装,maven中央库可引用

来源:互联网 发布:linux shell usleep 编辑:程序博客网 时间:2024/06/07 09:25

  一直以来关于持久层框架选择的讨论都比较多,网上查了下比较,大致得出的结果:hibernate太繁,springjdbc太简, mybatis 刚好,可见如今选用mybatis的势头也越来越明显。毕竟mybatis有DAO模版,强大的代码生成工具,这些都是在做开发的时候很容易提高效率的。

  但我个人偏向喜欢用Jdbctemplate,Jdbctemplate运行期更高效、内嵌Spring框架中、支持基于AOP的声明式事务,并且方便扩展,但是相信使用过Jdbctemplate的朋友应该知道,需要写一大堆的Rowmapper,而且开发完成后,由于sql是手写的,很可能会出现低级错误,这些都是Jdbctemplate的弊端,稍微有心的朋友这里肯定会选择自己封装一次。

  切入正题,现在我分享一下自己实现的基于mysql Jdbctemplate 的上层封装,费了九牛二虎之力,我将自己的代码上传到了maven中央库。

<dependency><groupId>com.github.11dong</groupId><artifactId>codes-common</artifactId><version>1.0.1</version></dependency>

  这里的实现我不做详解,下面讲讲如何使用。

  项目若使用此jar包无需做过多配置,项目数据源配置按正常的Jdbctemplate配置即可:

<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close"><property name="driverClassName" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><!-- 初始化连接大小 --><property name="initialSize" value="20" /><!-- 连接池最大使用连接数量 --><property name="maxActive" value="100" /><!-- 连接池最小空闲 --><property name="minIdle" value="20" /><!-- 获取连接最大等待时间 --><property name="maxWait" value="60000" /><property name="poolPreparedStatements" value="true" /><property name="maxPoolPreparedStatementPerConnectionSize"value="33" /><!-- 用来检测有效sql <property name="validationQuery" value="${validationQuery}" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> --><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="60000" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="25200000" /><!-- 打开removeAbandoned功能 --><property name="removeAbandoned" value="true" /><!-- 1800秒,也就是30分钟 --><property name="removeAbandonedTimeout" value="1800" /><!-- 关闭abanded连接时输出错误日志 --><property name="logAbandoned" value="true" /><!-- 监控数据库 --><property name="filters" value="mergeStat" /></bean><!-- 数据源 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean></beans>  
  实体类的创建:

package cc.dto;import java.io.Serializable;import java.util.Date;import com.zd.jdbcutil.DbColumn;import com.zd.jdbcutil.DbColumn.ColumType;import com.zd.jdbcutil.DbTable;@DbTable("sys_user")public class UserDto implements Serializable {    /**     * 用户信息     */    private static final long serialVersionUID = 4100310788962936416L;    @DbColumn(key = true)    private String id;        @DbColumn("username") //与数据库字段不同需要注解说明    private String userName;        private Date created;    private Integer state;    private Integer sex;        //-----非本数据库的额外字段------    @DbColumn(type = ColumType.QUERY_ONLY) //只允许查询不允许写入,如 left join 时使用    private String roleid;        @DbColumn(type = ColumType.IGNORE) //直接忽略,不查不写    private String flag;            public String getRoleid() {        return roleid;    }    public void setRoleid(String roleid) {        this.roleid = roleid;    }    public String getFlag() {        return flag;    }    public void setFlag(String flag) {        this.flag = flag;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getUserName() {        return userName;    }    public void setUserName(String userName) {        this.userName = userName;    }    public Date getCreated() {        return created;    }    public void setCreated(Date created) {        this.created = created;    }    public Integer getState() {        return state;    }    public void setState(Integer state) {        this.state = state;    }    public Integer getSex() {        return sex;    }    public void setSex(Integer sex) {        this.sex = sex;    }}
  这里的实体类类名上需要声明该类对应的数据库名称,数据库字段名称与实体类名称一一对应,区分大小写,若有字段不对应需要注解说明(userName),如果有非次表内的数据也需要注解说明它的使用情况。

  建好实体类后,接下来的工作就非常简单了。

  持久层:

  1、需要创建一个自己的BaseDao来继承工具包里的BaseDao,主要提供JdbcTemplate对象,若项目有多个库,可以构建多个MyBaseDaoImpl来实现,只需声明jdbcTemplate注解名,相互无干扰。

package cc.dao.impl;import java.io.Serializable;import javax.annotation.Resource;import org.springframework.jdbc.core.JdbcTemplate;import com.zd.jdbcutil.BaseDaoImpl;public abstract class MyBaseDaoImpl<T extends Serializable> extends BaseDaoImpl<T> {@Resource(name = "jdbcTemplate")//以配置文件名称为准private JdbcTemplate jdbcTemplate;public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}}

  2、单表的接口与实现类,无需任何方法

package cc.dao;import com.zd.jdbcutil.IBaseDao;import cc.dto.UserDto;public interface IUserDao extends IBaseDao<UserDto> {}

package cc.dao.impl;import org.springframework.stereotype.Repository;import cc.dao.IUserDao;import cc.dto.UserDto;@Repositorypublic class UserDaoImpl extends MyBaseDaoImpl<UserDto> implements IUserDao {}

  业务层接口与实现:

 

package cc.service;import com.zd.jdbcutil.IBaseService;import cc.dto.UserDto;public interface IUserDataService extends IBaseService<UserDto> {}

package cc.service.impl;import java.util.Map;import org.springframework.stereotype.Service;import com.zd.jdbcutil.BaseServiceImpl;import cc.dto.UserDto;import cc.service.IUserDataService;@Servicepublic class UserDataServiceImpl extends BaseServiceImpl<UserDto> implements IUserDataService {public Map<String, Object> genMapCondition(UserDto obj) {// TODO Auto-generated method stubreturn null;}}

这里的map是提供查询的筛选条件

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


以上创建完后就可以编写测试接口了:

package cc.controller;import java.util.Date;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.zd.jdbcutil.ConditionBuilder;import cc.dto.UserDto;import cc.service.IUserDataService;@Controller@RequestMapping("/test")public class TestController {@Autowiredprivate IUserDataService service;/** * 插入 *  * @return */@RequestMapping("/insert.do")@ResponseBodypublic Object insert() {UserDto user = new UserDto();user.setId("0dce718273b54d9ea635adaacb6642ea");user.setUserName("周杰伦");user.setCreated(new Date());user.setSex(0);user.setState(1);return service.insert(user);}/** * 修改 *  * @return */@RequestMapping("/update.do")@ResponseBodypublic Object update() {UserDto user = new UserDto();user.setId("0dce718273b54d9ea635adaacb6642ea");user.setUserName("林俊杰");return service.updateById(user);}/** * 查询 *  * @return */@RequestMapping("/query.do")@ResponseBodypublic Object query() {return service.query(new ConditionBuilder.Builder().equalTo("username", "周杰伦").build());}/** * 修改 *  * @return */@RequestMapping("/delete.do")@ResponseBodypublic Object delete() {return service.deleteById("0dce718273b54d9ea635adaacb6642ea");}}
  这里如果按照我写的方式来继承工具包里的接口与实现,开发就会变得很简单。

  相信朋友会有疑问,如果我要多表联查,或者复杂条件的话,怎么实现,我这里提供了两个工具类(ConditionBuilder,JoinQuery)与对应接口,可以实现,具体怎么做,可以查看我的源代码