用Freemarker、Dom4j、cglib、Spring-jdbc设计类似MyBatis的数据访问框架带分页功能

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。总的来说作为项目的数据访问层,是一个非常不错的选择。那么为什么又要重新设计一个类似的数据访问框架呢?

  1. 在使用mybatis的过程中,我们在写mapping映射的xml文件时,有些细节需要特别注意,比如说select类型的逗号处理。另外,每一个映射xml文件开头一般会有一个庞大的resultMap标签。
  2. 对应数据库每一个表,一般都会有一个xxxMapperService.java文件对应,导致项目工程里有大量的数据访问interface。
  3. 可以观察到,SQL语句mapping xml文件写法与freemarker框架使用的ftl语法有诸多相似的地方,为何不引入freemarker强大的动态模板替换功能呢?
  4. mybatis在与实体class映射过程中用到了反射,这一块有很大的优化空间,为何不引入cglib提升效率呢。

话不多说,直接上代码,目前代码托管在GitHub上,地址:https://github.com/Lydck/framework-dal.git。功能还不全,但已实现当初的大部分想法,欢迎大家加入!

框架映射文件xml定义:


	
	
			and USER_ID = :userId
		
		<#if userName??>
			and user_name like '%'||:userName||'%'
		
		<#if age??>
			and age = :age
		
		<#if password??>
			and password = :password
		
	]]>
	
	
	
			and user_name = :userName
		
		<#if age??>
			and age = :age
		
	]]>
	

实体对象映射注解:

Table注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {

	/** 数据库表名*/
	String value();

}

数据列注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

	/** Column列名*/
	String value() default "";
	
	/** 数据类型*/
	Class type() default String.class;
}

主键注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ID {

	/** 主键名称,不指定的话,默认为被标记字段的属性名称*/
	String value();
	
	/**Oracle数据递增序列名称
	 * @return
	 */
	String sequence() default "";
}

公共对外接口定义:

/**数据库常规操作
 * @author xiangyj
 *
 */
public interface DalClient {

	/**单表添加操作
	 * @param 
	 * @param entity 对象实体
	 * @return
	 */
	 Number persist(T entity);
	
    /**单表修改操作 根据主键修改记录
     * @param entity
     * @return 更新成功的记录数
     */
	 int merge(T entity);
	
	/**单表删除操作 根据主键删除记录
	 * @param 
	 * @param entity
	 * @return 删除成功的记录数
	 */
	 int remove(T entity);
	
	/**单表查询操作 根据主键查询记录
	 * @param 
	 * @param entity
	 * @return
	 */
	 T find(T entity);
	
	/**根据sqlId查询单个对象,返回requiredType类型对象,查不到返回null, 查询多个返回第一个
	 * @param 
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @param requiredType 结果实体类型
	 * @return
	 */
	 T queryForObject(String sqlId, Map paramMap, Class requiredType);
	
	/**根据sqlId查询单个对象,返回requiredType类型对象,查不到返回null, 查询多个返回第一个
	 * @param 
	 * @param sqlId SQLID
	 * @param param 查询参数
	 * @param requiredType 结果实体类型
	 * @return
	 */
	 T queryForObject(String sqlId, Object param, Class requiredType);
	
	/**根据sqlId查询单个对象,返回rowMapper类型对象, 查不到返回null, 查询多个返回第一个
	 * @param 
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @param rowMapper 结果映射
	 * @return
	 */
	 T queryForObject(String sqlId, Map paramMap, RowMapper rowMapper);
	
	/**根据sqlId查询单个对象,返回Map集合,key是数据库字段 ,查不到返回null,查询多个返回第一个
	 * @param sqlId
	 * @param paramMap
	 * @return
	 */
	Map queryForMap(String sqlId, Map paramMap);
	
	/**根据sqlId查询单个对象,返回Map集合,key是数据库字段 ,查不到返回null,查询多个返回第一个
	 * @param sqlId
	 * @param param
	 * @return
	 */
	Map queryForMap(String sqlId, Object param);
	
	/**根据sqlId查询多个对象,返回requiredType类型对象List集合
	 * @param 
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @param requiredType 结果实体类型
	 * @return
	 */
	 List queryForList(String sqlId, Map paramMap, Class requiredType);
	
	/**根据sqlId查询,返回Map集合List,key是数据库字段
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @return
	 */
	List> queryForList(String sqlId, Map paramMap);
	
	/**根据sqlId查询多个对象,返回rowMapper类型对象List集合
	 * @param 
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @param rowMapper 结果映射
	 * @return
	 */
	 List queryForList(String sqlId, Map paramMap, RowMapper rowMapper);
	
	/**根据sqlId执行,返回执行成功的记录条数
	 * @param sqlId SQLID
	 * @param paramMap 查询参数
	 * @return
	 */
	int execute(String sqlId, Map paramMap);
	
    /**根据sqlId执行,返回执行成功的记录条数
     * @param sqlId SQLID
     * @param param 参数对象
     * @return
     */
    int execute(String sqlId, Object param);
    
    /**根据sqlId执行,批量执行
     * @param sqlId SQLID
     * @param batchValues 批处理对象
     * @return 执行成功的记录数
     */
    int[] batchUpdate(String sqlId, Map[] batchValues);
    
    /**根据sqlId执行,批量执行
     * @param 
     * @param sqlId SQLID
     * @param batchValues 批处理对象
     * @return 执行成功的记录数
     */
     int[] batchUpdate(String sqlId, @SuppressWarnings("unchecked") T... batchValues);
    
	/**
	 * 存储过程调用 存储过程调用时,需要加上schema
	 * 
	 * @param sqlId         SQL语句ID
	 * @param paramMap      查询参数
	 * @param sqlParameters SqlCommand参数
	 * @return 调用结果
	 */
	Map call(String sqlId, Map paramMap, List sqlParameters);

数据库表映射对象定义:

@Setter
@Getter
@Table("TMS_USER")
public class UserEntity implements Serializable {

	private static final long serialVersionUID = 1L;

	@ID(value = "USER_ID", sequence = "TESTUSER")
	private Integer userId;

	@Column("USER_NAME")
	private String userName;
	
	@Column("PASSWORD")
	private String password;
	
	private String email;
	
	@Column("EMP_CODE")
	private String empCode;
	
	@Column("DEPT_ID")
	private String deptId;
	
	@Column("ORG_ROLE")
	private String orgRole;
	
}

到此,数据访问配置完成,从上面来看,要引入该框架:

1.只需提供SQL语句映射文件,根据namespace.sqlid找到具体要执行的语句

2.实例化公共接口实现类,注入项目中的数据源DataSource

3.调用CRUD

是不是非常方便!

你可能感兴趣的:(原创,框架,分页查询,Mybatis,Cglib,Freemarker,framework-dal)