mybatis帮助程序猿省去了很多工作了,需要结合好BaseDao与BaseService,这里就提供下我所使用的BaseXXX。
前提,mybatis的映射文件是采用mybatis-generator自动生成的(mybatis-generator使用方法)
1、BaseDao,我们知道在mybatis与SpringMVC结合的时候,Dao层只需要写interface即可,剩下的实现工作将由mybatis自动为我们实现,这个BaseDao省去interface这层,采用SpringMvc的@Repository标签进行注入管理,上代码:
- import java.io.Serializable;
- import java.lang.reflect.InvocationTargetException;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.apache.commons.beanutils.PropertyUtils;
- import org.apache.ibatis.session.RowBounds;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.mybatis.spring.support.SqlSessionDaoSupport;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Repository;
- import com.alibaba.dubbo.common.utils.CollectionUtils;
- import com.github.pagehelper.PageHelper;
- import com.github.pagehelper.PageInfo;
- //工具类
- import com.ivan.core.util.GenericsUtils;
- //分页Form
- import com.ivan.core.util.page.PageForm;
- @Repository("baseDao")
- public class BaseDao<T, PK extends Serializable> extends SqlSessionDaoSupport implements Serializable {
- private static final long serialVersionUID = 7623507504198633838L;
- private final String POSTFIX = "Dao";
- private final String _INSERT = ".insert";
- private final String _INSERTSELECTIVE = ".insertSelective";
- private final String _SELECTBYPRIMARYKEY = ".selectByPrimaryKey";
- private final String _UPDATEBYPRIMARYKEY = ".updateByPrimaryKey";
- private final String _UPDATEBYPRIMARYKEYSELECTIVE = ".updateByPrimaryKeySelective";
- private final String _DELETEBYPRIMARYKEY = ".deleteByPrimaryKey";
- @Autowired
- public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
- super.setSqlSessionFactory(sqlSessionFactory);
- }
- /*GenericsUtils为工具类,请见下方代码
- 泛型获得XXXEntity,将其转换为XXXEntityDao,具体操作替换掉Entity变成XXXDao,对应Mapper.xml中的namespace命名
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public String getNampSpace() {
- Class<T> clazz = (Class)GenericsUtils.getSuperClassGenricType(this.getClass());
- String simpleName = clazz.getSimpleName() + POSTFIX;
- return simpleName;
- }
- public int insert(T entity) {
- return getSqlSession().insert(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _INSERT, entity);
- }
- public int insertSelective(T record) {
- return getSqlSession().insert(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _INSERTSELECTIVE, record);
- }
- public T selectByPrimaryKey(PK id) {
- return getSqlSession().selectOne(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _SELECTBYPRIMARYKEY, id);
- }
- public int updateByPrimaryKey(T record) {
- return getSqlSession().update(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _UPDATEBYPRIMARYKEY, record);
- }
- public int updateByPrimaryKeySelective(T record) {
- return getSqlSession().update(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _UPDATEBYPRIMARYKEYSELECTIVE, record);
- }
- public int deleteByPrimaryKey(PK id) {
- return getSqlSession().delete(
- (this.getNampSpace().contains("Entity") ? this.getNampSpace().replace("Entity", "")
- : this.getNampSpace()) + _DELETEBYPRIMARYKEY, id);
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public PageInfo<T> pageFind(String statementKey, PageForm pageForm, Object parameter,
- Boolean isSimplePage) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Map params = new HashMap();
- if (parameter != null) {
- if (parameter instanceof Map) {
- params.putAll((Map) parameter);
- } else {
- Map parameterObject = PropertyUtils.describe(parameter);
- params.putAll(parameterObject);
- }
- }
- PageHelper.startPage(pageForm.getPage(), pageForm.getRows());
- List<T> list = getSqlSession().selectList(statementKey, params);
- PageInfo<T> pageInfo = new PageInfo(list);
- return pageInfo;
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public List<T> findTop(int top, String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Map params = new HashMap();
- if (parameter != null) {
- if (parameter instanceof Map) {
- params.putAll((Map) parameter);
- } else {
- Map parameterObject = PropertyUtils.describe(parameter);
- params.putAll(parameterObject);
- }
- }
- List<T> list = getSqlSession().selectList(statementKey, params, new RowBounds(0, top));
- return list;
- }
- public T findTopOne(String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- List<T> list = findTop(1, statementKey, parameter);
- return CollectionUtils.isEmpty(list) ? null : list.get(0);
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public <M> PageInfo<M> pageFindModel(String statementKey, PageForm pageForm, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Map params = new HashMap();
- if (parameter != null) {
- if (parameter instanceof Map) {
- params.putAll((Map) parameter);
- } else {
- Map parameterObject = PropertyUtils.describe(parameter);
- params.putAll(parameterObject);
- }
- }
- PageHelper.startPage(pageForm.getPage(), pageForm.getRows());
- List<M> list = getSqlSession().selectList(statementKey, params);
- PageInfo<M> pageInfo = new PageInfo(list);
- return pageInfo;
- }
- }
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- import javax.servlet.http.HttpSession;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- /**
- * 泛型工具类
- *
- * @author <a href="http://www.blogjava.net/lishunli/"
- * target="_jeecg">ShunLi</a>
- * @notes Created on 2010-1-21<br>
- * Revision of last commit:$Revision: 1.1 $<br>
- * Author of last commit:$Author: ghp $<br>
- * Date of last commit:$Date: 2010-01-25 16:48:17 +0800 (周一, 25 一月 2010)
- * $<br>
- * <p>
- */
- public class GenericsUtils {
- /**
- * 通过反射,获得指定类的父类的泛型参数的实际类型. 如BuyerServiceBean extends DaoSupport<Buyer>
- *
- * @param clazz
- * clazz 需要反射的类,该类必须继承范型父类
- * @param index
- * 泛型参数所在索引,从0开始.
- * @return 范型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- public static Class getSuperClassGenricType(Class clazz, int index) {
- Type genType = clazz.getGenericSuperclass();// 得到泛型父类
- // 如果没有实现ParameterizedType接口,即不支持泛型,直接返回Object.class
- if (!(genType instanceof ParameterizedType)) {
- return Object.class;
- }
- // 返回表示此类型实际类型参数的Type对象的数组,数组里放的都是对应类型的Class, 如BuyerServiceBean extends
- // DaoSupport<Buyer,Contact>就返回Buyer和Contact类型
- Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
- if (index >= params.length || index < 0) {
- throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
- }
- if (!(params[index] instanceof Class)) {
- return Object.class;
- }
- return (Class) params[index];
- }
- /**
- * 通过反射,获得指定类的父类的第一个泛型参数的实际类型. 如BuyerServiceBean extends DaoSupport<Buyer>
- *
- * @param clazz
- * clazz 需要反射的类,该类必须继承泛型父类
- * @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- @SuppressWarnings("unchecked")
- public static Class getSuperClassGenricType(Class clazz) {
- return getSuperClassGenricType(clazz, 0);
- }
- /**
- * 通过反射,获得方法返回值泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
- *
- * @param Method
- * method 方法
- * @param int index 泛型参数所在索引,从0开始.
- * @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- @SuppressWarnings("unchecked")
- public static Class getMethodGenericReturnType(Method method, int index) {
- Type returnType = method.getGenericReturnType();
- if (returnType instanceof ParameterizedType) {
- ParameterizedType type = (ParameterizedType) returnType;
- Type[] typeArguments = type.getActualTypeArguments();
- if (index >= typeArguments.length || index < 0) {
- throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
- }
- return (Class) typeArguments[index];
- }
- return Object.class;
- }
- /**
- * 通过反射,获得方法返回值第一个泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
- *
- * @param Method
- * method 方法
- * @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- @SuppressWarnings("unchecked")
- public static Class getMethodGenericReturnType(Method method) {
- return getMethodGenericReturnType(method, 0);
- }
- /**
- * 通过反射,获得方法输入参数第index个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String,
- * Buyer> maps, List<String> names){}
- *
- * @param Method
- * method 方法
- * @param int index 第几个输入参数
- * @return 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回空集合
- */
- @SuppressWarnings("unchecked")
- public static List<Class> getMethodGenericParameterTypes(Method method, int index) {
- List<Class> results = new ArrayList<Class>();
- Type[] genericParameterTypes = method.getGenericParameterTypes();
- if (index >= genericParameterTypes.length || index < 0) {
- throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
- }
- Type genericParameterType = genericParameterTypes[index];
- if (genericParameterType instanceof ParameterizedType) {
- ParameterizedType aType = (ParameterizedType) genericParameterType;
- Type[] parameterArgTypes = aType.getActualTypeArguments();
- for (Type parameterArgType : parameterArgTypes) {
- Class parameterArgClass = (Class) parameterArgType;
- results.add(parameterArgClass);
- }
- return results;
- }
- return results;
- }
- /**
- * 通过反射,获得方法输入参数第一个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String, Buyer>
- * maps, List<String> names){}
- *
- * @param Method
- * method 方法
- * @return 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回空集合
- */
- @SuppressWarnings("unchecked")
- public static List<Class> getMethodGenericParameterTypes(Method method) {
- return getMethodGenericParameterTypes(method, 0);
- }
- /**
- * 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
- *
- * @param Field
- * field 字段
- * @param int index 泛型参数所在索引,从0开始.
- * @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- @SuppressWarnings("unchecked")
- public static Class getFieldGenericType(Field field, int index) {
- Type genericFieldType = field.getGenericType();
- if (genericFieldType instanceof ParameterizedType) {
- ParameterizedType aType = (ParameterizedType) genericFieldType;
- Type[] fieldArgTypes = aType.getActualTypeArguments();
- if (index >= fieldArgTypes.length || index < 0) {
- throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
- }
- return (Class) fieldArgTypes[index];
- }
- return Object.class;
- }
- /**
- * 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
- *
- * @param Field
- * field 字段
- * @param int index 泛型参数所在索引,从0开始.
- * @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
- * <code>Object.class</code>
- */
- @SuppressWarnings("unchecked")
- public static Class getFieldGenericType(Field field) {
- return getFieldGenericType(field, 0);
- }
- /**
- * 根据实体得到实体的所有属性
- * @param objClass
- * @return
- * @throws ClassNotFoundException
- */
- public static String[] getColumnNames(String objClass) throws ClassNotFoundException {
- String[] wageStrArray = null;
- if (objClass != null) {
- Class class1 = Class.forName(objClass);
- Field[] field = class1.getDeclaredFields();// 这里便是获得实体Bean中所有属性的方法
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < field.length; i++) {// 这里不多说了
- sb.append(field[i].getName());
- // 这是分割符 是为了去掉最后那个逗号
- // 比如 如果不去最后那个逗号 最后打印出来的结果是 "id,name,"
- // 去了以后打印出来的是 "id,name"
- if (i < field.length - 1) {
- sb.append(",");
- }
- }
- // split(",");这是根据逗号来切割字符串使字符串变成一个数组
- wageStrArray = sb.toString().split(",");
- return wageStrArray;
- } else {
- return wageStrArray;
- }
- }
- public static Object[] field2Value(Field[] f, Object o) throws Exception {
- Object[] value = new Object[f.length];
- for (int i = 0; i < f.length; i++) {
- value[i] = f[i].get(o);
- }
- return value;
- }
- /**
- * returns the current http session object
- *
- * @return session
- */
- public HttpSession getSession() {
- HttpSession session=null;
- ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
- HttpSession contextSess = attr == null ? session : attr.getRequest().getSession(true);
- return contextSess;
- }
- /**
- * 得到实体类
- * @param objClass 实体类包含包名
- * @return
- */
- public static Class getEntityClass(String objClass){
- Class entityClass = null;
- try {
- entityClass = Class.forName(objClass);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return entityClass;
- }
- /**
- * 定义字符集
- * @param
- * @return
- */
- private static char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
- 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'y', 'z', 'A', 'B','C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
- 'Z'}; //72个字符集
- /**
- *
- * @param passLength
- * 随机密码长度
- * @param count
- * 随机密码个数
- * @return 随机密码数组
- */
- public static String getPasswords(int passLength) {
- String passwords = "";// 新建一个长度为指定需要密码个数的字符串数组
- Random random = new Random();
- StringBuilder password = new StringBuilder("");// 保存生成密码的变量
- for (int m = 1; m <= passLength; m++) {// 内循环 从1开始到密码长度 正式开始生成密码
- password.append(chars[random.nextInt(62)]);// 为密码变量随机增加上面字符中的一个
- }
- passwords = password.toString();// 将生成出来的密码赋值给密码数组
- return passwords;
- }
- }
3、BaseService接口,为什么这层要选择接口来实现呢?有很多需要前后分离的应用,暴露的服务就是接口暴露Service层,所以采用接口。
- import java.io.Serializable;
- import java.lang.reflect.InvocationTargetException;
- import java.util.List;
- @SuppressWarnings("hiding")
- public interface BaseService<T, Serializable> {
- public int insert(T record);
- public int insertSelective(T record);
- public T selectByPrimaryKey(String id);
- public int updateByPrimaryKey(T record);
- public int updateByPrimaryKeySelective(T record);
- public int deleteByPrimaryKey(String id);
- public List<T> findTop(int top, String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
- public T findTopOne(String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
- }
4、BaseService接口的实现类BaseServiceImpl,需要注入BaseDao(其中必须对BaseDao进行set,否则无法获取具体泛型)
- import java.io.Serializable;
- import java.lang.reflect.InvocationTargetException;
- import java.util.List;
- import org.springframework.beans.factory.annotation.Autowired;
- import com.alibaba.dubbo.config.annotation.Service;
- import com.ivan.api.base.BaseService;
- import com.ivan.base.BaseDao;
- @Service
- public abstract class BaseServiceImpl<T> implements BaseService<T, Serializable>{
- @Autowired
- private BaseDao<T, Serializable> baseDao;
- public BaseDao<T, Serializable> getBaseDao() {
- return baseDao;
- }
- public void setBaseDao(BaseDao<T, Serializable> baseDao) {
- this.baseDao = baseDao;
- }
- public int insert(T entity) {
- return baseDao.insert(entity);
- }
- public int insertSelective(T record) {
- return baseDao.insertSelective(record);
- }
- public T selectByPrimaryKey(String id) {
- return baseDao.selectByPrimaryKey(id);
- }
- public int updateByPrimaryKey(T record) {
- return baseDao.updateByPrimaryKey(record);
- }
- public int updateByPrimaryKeySelective(T record) {
- return baseDao.updateByPrimaryKeySelective(record);
- }
- public int deleteByPrimaryKey(String id) {
- return baseDao.deleteByPrimaryKey(id);
- }
- public List<T> findTop(int top, String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- return baseDao.findTop(top, statementKey, parameter);
- }
- public T findTopOne(String statementKey, Object parameter) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- return baseDao.findTopOne(statementKey, parameter);
- }
- }
5、Mapper.xml文件的定义,需要注意的是namespace的命名,会通过这个命名找到具体的mapper文件,进行数据的操作。
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
- <mapper namespace="UserDao" >
- <resultMap id="BaseResultMap" type="com.ivan.entity.UserEntity" >
- <id column="id" property="id" jdbcType="VARCHAR" />
- <result column="name" property="name" jdbcType="VARCHAR" />
- <result column="age" property="age" jdbcType="INTEGER" />
- </resultMap>
- <sql id="Base_Column_List" >
- id, name, age
- </sql>
- <select id="selectAll" resultMap="BaseResultMap">
- select
- <include refid="Base_Column_List" />
- from user
- </select>
- <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="String" >
- select
- <include refid="Base_Column_List" />
- from user
- where id = #{id,jdbcType=INTEGER}
- </select>
- <delete id="deleteByPrimaryKey" parameterType="String" >
- delete from user
- where id = #{id,jdbcType=INTEGER}
- </delete>
- <insert id="insert" parameterType="com.ivan.entity.UserEntity" >
- insert into user (id, name, age
- )
- values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}
- )
- </insert>
- <insert id="insertSelective" parameterType="com.ivan.entity.UserEntity" >
- insert into user
- <trim prefix="(" suffix=")" suffixOverrides="," >
- <if test="id != null" >
- id,
- </if>
- <if test="name != null" >
- name,
- </if>
- <if test="age != null" >
- age,
- </if>
- </trim>
- <trim prefix="values (" suffix=")" suffixOverrides="," >
- <if test="id != null" >
- #{id,jdbcType=VARCHAR},
- </if>
- <if test="name != null" >
- #{name,jdbcType=VARCHAR},
- </if>
- <if test="age != null" >
- #{age,jdbcType=INTEGER},
- </if>
- </trim>
- </insert>
- <update id="updateByPrimaryKeySelective" parameterType="com.ivan.entity.UserEntity" >
- update user
- <set >
- <if test="name != null" >
- name = #{name,jdbcType=VARCHAR},
- </if>
- <if test="age != null" >
- age = #{age,jdbcType=INTEGER},
- </if>
- </set>
- where id = #{id,jdbcType=VARCHAR}
- </update>
- <update id="updateByPrimaryKey" parameterType="com.ivan.entity.UserEntity" >
- update user
- set name = #{name,jdbcType=VARCHAR},
- age = #{age,jdbcType=INTEGER}
- where id = #{id,jdbcType=VARCHAR}
- </update>
- </mapper>
6、具体的使用方法:
a、定义UserDao:
- @Repository("userDao")
- public class UserDao extends BaseDao<UserEntity, Serializable>{
- /**
- *
- */
- private static final long serialVersionUID = 9152785684346322571L;
- }
- public interface UserService extends BaseService<UserEntity, Serializable>{
- }
c、实现UserService接口
- @Service
- public class UserServiceImpl extends BaseServiceImpl<UserEntity> implements UserService{
- }
d、调用UserService接口
- @Controller
- @RequestMapping("/user")
- public class UserController {
- @SuppressWarnings("unused")
- private static final Logger logger = LoggerFactory.getLogger(UserController.class);
- @Reference
- private UserService userService;
- }
以上,可以整合到前几篇关于dubbo的工程中。