mybatis通用DAO
花了几天的时间研究了一下mybatis的源代码,觉得这个框架还是很不错的。但是有一些缺陷的地方。
先来说说它和别的框架比起来我认为的好处:
(1)sql外置,把sql文件写在配置文件中加上强大的动态sql支持。
(2)利用cjk动态代理,实现配置文件映射接口。
这样我们在使用这套orm框架的时候就可以不再写那个拼接sql语句的dao实现类(dao-impl class),把dao实现类的工作都移交给那些*mapper.xml文件,如果数据库查询业务需要修改sql的话,那么只需要修改xml文件中的sql语句。
需要扩展的地方:
(1)没有内置物理分页的实现。
我们一般的习惯都是返回我们自己的分页实现类,网上大多的mybatis分页实现都是先返回分页列表,再查下返回总页数,然后处理成我们自己的分页类。我自己也写了一个分页,把这部分工作交给mybatis来处理,以后会把代码贴出来。
(2)公用范型接口dao
公用范型接口dao类几乎成为我们开发中最长使用的,把一些长操作的方法封装一下,供我们的业务dao调用,但是在mybatis中,我现在不想再写dao的实现类,只有接口类,取缔他的是mapper-xml文件,这样如何才能封装我们的公用方法呢。
幸好mybatis提供了插件拦截器,我们可以在不修改mybatis源码的基础上来扩展它的功能。
好忙啊,花了些时间写了一个范型接口dao,还没有经过验证,先贴上代码。
使用方法很简单,只要你使用MappInterceptor这个拦截器,在你的Mapper接口中继承这个IGenericDao这样 公用的方法就可以使用了,这样的好处是在一般业务的类中不用再写Dao的实现,直接使用 IGenericDao中提供的方法就ok
公用dao,你的接口只要继承这个dao就可以使用里面的方法。
package org.cf.guott.mybatis; import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.cf.guott.mybatis.pagination.PageMyBatis; public interface IGenericDao<T,PK> { @Select("MapperGD.find.entityById")
public T findEntityById(PK id); @Select("MapperGD.find.entitys")
public List<T> findEntity(Object... obj); @Select("MapperGD.find.ListByLike")
public List<T> findLikeEntity(Object... obj); @Insert("MapperGD.insert.entity")
public void insertEntity(T t); @Update("MapperGD.update.entity")
public void updateEntityById(T entity); @Delete("MapperGD.delete.id")
public void deleteById(PK id); @Delete("MapperGD.delete.condition")
public void deleteByCondition(Object param); @Select("MapperGD.find.entity.queryByVo")
public PageMyBatis<T> queryByVo(int i,int c,Object... obj); @Select("MapperGD.find.entity.queryByVoLike")
public PageMyBatis<T> LikequeryByVo(int i,int c,Object... obj); }
这个一个拦截器,来处理你的公用dao中的方法
package org.cf.guott.mybatis.dbmapper.interceptor; import java.util.Map;
import java.util.Properties; import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.cf.guott.mybatis.helpers.MapperSqlHelper;
import org.cf.guott.mybatis.pagination.MappedStatmentHelper; @Intercepts({
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
,@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class})
}) public class MappInterceptor implements Interceptor{
private final static String _sql_regex = ".*MapperGD.*"; @SuppressWarnings("unchecked")
private void processIntercept(final Object[] queryArgs) {
final MappedStatement ms = (MappedStatement) queryArgs[0];
final Object parameter = queryArgs[1];
String mapperSQL = ms.getBoundSql(parameter).getSql();
BoundSql boundSQL = ms.getBoundSql(parameter); Class<?> entityclazz = MappedStatmentHelper.getEntityClazz(ms.getResource());
queryArgs[0] = MappedStatmentHelper.setMSReturnSetMap(ms, entityclazz); boolean interceptor = mapperSQL.matches(_sql_regex);
if(!interceptor){
return;
}
if(entityclazz == null){
throw new RuntimeException("使用公共dao必須給mapper接口的@MyBatisRepository(User.class) 注解設置值.");
} String new_sql = MapperSqlHelper.getExecuSQL(entityclazz,mapperSQL,parameter); BoundSql newBoundSql = MappedStatmentHelper.copyFromBoundSql(ms,
boundSQL, new_sql);
MappedStatement newMs = MappedStatmentHelper
.copyFromMappedStatement(ms, newBoundSql);
queryArgs[0] = newMs; }
public Object intercept(Invocation invocation) throws Throwable { processIntercept(invocation.getArgs()); return invocation.proceed();
}
public Object plugin(Object o) {
return Plugin.wrap(o, this);
}
public void setProperties(Properties arg0) {
}
}
这个类来处理你的sql语句
package org.cf.guott.mybatis.helpers; import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map; import org.apache.commons.lang3.reflect.FieldUtils;
import org.cf.guott.mybatis.annotation.MyBatisColumn;
import org.cf.guott.mybatis.annotation.MyBatisRepository;
import org.cf.guott.mybatis.annotation.MybatisID;
import org.cf.guott.mybatis.annotation.MybatisTable;
import org.cf.guott.mybatis.entity.User; public class MapperSqlHelper{ public static final Class<? extends Annotation> MYBATISREPOSITORY = MyBatisRepository.class;
public static final Class<? extends Annotation> MYBATISTABLE = MybatisTable.class;
public static final Class<? extends Annotation> MYBATISCOLUMN = MyBatisColumn.class;
public static final Class<? extends Annotation> MYBATISID = MybatisID.class; public String getUpdateSQL(){
return null;
}
/**
* 传入mapper接口class
* @param mapperclazz
* @return
*/
private String insertEntity(Class<?> clazz){
StringBuilder sql = new StringBuilder();
StringBuilder intosql = new StringBuilder();
StringBuilder valuessql = new StringBuilder();
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("INSERT INTO "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("INSERT INTO "+clazz.getName());
}else{
sql.append("INSERT INTO "+antable.value());
}
}
Field[] files = clazz.getDeclaredFields();
intosql.append("(");
for(Field file : files){
file.setAccessible(true);
if(file.isAnnotationPresent(MYBATISCOLUMN)){
MyBatisColumn anColumn = (MyBatisColumn)file.getAnnotation(MYBATISCOLUMN);
if(!anColumn.isAutoKey()){
if(anColumn.value().equals("")){
intosql.append(file.getName()+",");
}else{
intosql.append(anColumn.value()+",");
}
}
}else{
intosql.append(file.getName()+",");
}
}
valuessql.append(" values (");
for(Field file : files){
file.setAccessible(true);
if(file.isAnnotationPresent(MYBATISCOLUMN)){
MyBatisColumn anColumn = (MyBatisColumn)file.getAnnotation(MYBATISCOLUMN);
if(!anColumn.isAutoKey()){
if(anColumn.value().equals("")){
valuessql.append("#{"+file.getName()+"},");
}else{
valuessql.append("#{"+file.getName()+"},");
}
}
}else{
valuessql.append("#{"+file.getName()+"},");
} }
return sql.append(intosql.substring(0, intosql.length()-1)).append(") ").append(valuessql.substring(0, valuessql.length()-1)).append(")").toString();
} /**
* 传入mapper接口class
* @param mapperclazz
* @return
*/
private String updateEntityById(Class<?> clazz){
StringBuilder sql = new StringBuilder();
StringBuilder set = new StringBuilder();
StringBuilder wheresql = new StringBuilder();
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("UPDATE "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("UPDATE "+clazz.getName());
}else{
sql.append("UPDATE "+antable.value());
}
}
Field[] files = clazz.getDeclaredFields();
set.append(" set ");
wheresql.append(" where 1=1 ");
for(Field file : files){
file.setAccessible(true);
if(file.isAnnotationPresent(MYBATISCOLUMN)){
MyBatisColumn anColumn = (MyBatisColumn)file.getAnnotation(MYBATISCOLUMN);
if(!anColumn.isID()){//判断字段不为主键
if(anColumn.value().equals("")){
set.append(file.getName()+" = #{"+file.getName()+"} ,");
}else{
set.append(anColumn.value()+" = #{"+file.getName()+"} ,");
}
}else{
if(anColumn.value().equals("")){
wheresql.append(" and "+file.getName()+" = #{"+file.getName()+"},");
}else{
wheresql.append(" and "+anColumn.value()+" = #{"+anColumn.value()+"},");
}
}
}else{
set.append(file.getName()+" = #{"+file.getName()+"} ,");
}
}
if(wheresql.equals(" where 1=1 ")){
throw new RuntimeException("实体变量没有设置ID字段值");
}
sql.append(set.substring(0, set.length()-1)).append(wheresql.substring(0, wheresql.length()-1));
return sql.toString();
}
private String findEntityAll(Class<?> clazz,Object args,boolean islike){
StringBuilder sql = new StringBuilder();
StringBuilder whereSQL = new StringBuilder(" where 1=1 ");
StringBuffer orderby = new StringBuffer();
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("select * from "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("select * from "+clazz.getSimpleName());
}else{
sql.append("select * from "+antable.value());
}
}
Object[] paramObjs = (Object[]) ((Map)args).get("array");
if(paramObjs != null && paramObjs.length>0){
Object param = paramObjs[0];
if(param != null ){
if(param instanceof Map){
Map<String,Object> map = (Map)param;
if(map.containsKey("orderby")){
orderby.append(" order by "+map.get("orderby"));
}
if(map.containsKey("sortby")){
orderby.append(" "+map.get("sortby")+" ");
}
for(String key : map.keySet())
{
if(islike)
whereSQL.append(" and "+key + " like '%" + map.get(key)+"%',");
else whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1)).append(orderby);
}else if(param instanceof Conditions){
Conditions<String,Object> map = (Conditions)param;
if(map.containsKey("orderby")){
orderby.append(" order by "+map.get("orderby"));
}
if(map.containsKey("sortby")){
orderby.append(" "+map.get("sortby")+" ");
}
for(String key : map.keySet())
{
if(key.equals("orderby") || key.equals("sortby")){
continue;
}
if(islike)
whereSQL.append(" and "+key + " like '%" + map.get(key)+"%',");
else whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1)).append(orderby);
}
}
}
return sql.toString();
}
private String findEntityById(Class<?> clazz){
StringBuilder sql = new StringBuilder();
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("select * from "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("select * from "+clazz.getSimpleName());
}else{
sql.append("select * from "+antable.value());
}
}
sql.append(" where 1=1 ");
Field[] files = clazz.getDeclaredFields();
boolean falg = false;
for(Field file : files){
file.setAccessible(true);
if(file.isAnnotationPresent(MyBatisColumn.class)){
MyBatisColumn anColumn = (MyBatisColumn)file.getAnnotation(MYBATISCOLUMN);
if(anColumn.isID()){//判断字段不为主键
falg = true;
if(anColumn.value().equals("")){
sql.append(" and "+file.getName()+" = #{"+file.getName()+"},");
}else{
sql.append(" and "+file.getName()+" = #{"+file.getName()+"},");
}
}
}
}
if(!falg){
throw new RuntimeException("不能通過id查詢實體,實體中沒有定義@mybatisID");
} return sql.subSequence(0, sql.length()-1).toString();
}
public String deleteById(Class<?> clazz){
StringBuilder sql = new StringBuilder();
StringBuilder wheresql = new StringBuilder(" where 1=1 ");
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("delete "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("delete "+clazz.getName());
}else{
sql.append("delete "+antable.value());
}
}
Field[] files = clazz.getDeclaredFields();
for(Field file : files){
file.setAccessible(true);
if(file.isAnnotationPresent(MYBATISCOLUMN)){
MyBatisColumn anColumn = (MyBatisColumn)file.getAnnotation(MYBATISCOLUMN);
if(anColumn.isID()){//判断字段不为主键
if(anColumn.value().equals("")){
wheresql.append(" and "+file.getName()+" = #{"+file.getName()+"},");
}else{
wheresql.append(" and "+anColumn.value()+" = #{"+anColumn.value()+"},");
}
}
}
}
if(wheresql.equals(" where 1=1 ")){
throw new RuntimeException("实体变量没有设置ID字段值");
}
sql.append(wheresql.substring(0,wheresql.length()-1));
return sql.toString();
}
public String queryByVo(Class<?> clazz,Object args,boolean islike){
StringBuilder sql = new StringBuilder();
StringBuilder whereSQL = new StringBuilder(" where 1=1 ");
StringBuilder orderbySQL = new StringBuilder("");
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("select * from "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("select * from "+clazz.getName());
}else{
sql.append("select * from "+antable.value());
}
}
if(args instanceof Map){
Map map = (Map)args;
Object[] arr = (Object[])map.get("param3");
if(arr.length>0){
Map<String,Object> params = (Map)arr[0];
if(params.containsKey("orderby")){
orderbySQL.append(" order by "+params.get("orderby"));
}
if(params.containsKey("sortby")){
orderbySQL.append(" "+params.get("sortby")+" ");
}
for(String key:params.keySet()){
if(key.equals("orderby") || key.equals("sortby")){
continue;
}
if(islike)
whereSQL.append(" and "+key + " like '%" + params.get(key)+"%',");
else whereSQL.append(" and "+key + " = '" + params.get(key)+"',");
}
}
} return sql.append(whereSQL.substring(0, whereSQL.length()-1)).append(orderbySQL).toString();
}
public String count(Class<?> clazz,Object args){
StringBuilder sql = new StringBuilder();
StringBuilder whereSQL = new StringBuilder(" where 1=1 ");
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("select count(*) from "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("select count(*) from "+clazz.getName());
}else{
sql.append("select count(*) from "+antable.value());
}
}
Object[] paramObjs = (Object[]) ((Map)args).get("array");
if(paramObjs != null && paramObjs.length>0){
Object param = paramObjs[0];
if(param != null ){
if(param instanceof Map){
Map<String,Object> map = (Map)param;
for(String key : map.keySet())
{
whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1));
}else if(param instanceof Conditions){
Conditions<String,Object> map = (Conditions)param;
for(String key : map.keySet())
{
whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1));
}
}
}
return sql.toString();
}
public String deleteByCondition(Class<?> clazz,Object param){
StringBuilder sql = new StringBuilder();
StringBuilder whereSQL = new StringBuilder(" where 1=1 ");
if(!clazz.isAnnotationPresent(MYBATISTABLE)){
sql.append("delete "+clazz.getName());
}else{
MybatisTable antable = (MybatisTable)clazz.getAnnotation(MYBATISTABLE);
if(antable.value() == ""){
sql.append("delete "+clazz.getName());
}else{
sql.append("delete "+antable.value());
}
}
if(param != null ){
if(param instanceof Map){
Map<String,Object> map = (Map)param;
for(String key : map.keySet())
{
whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1));
}else if(param instanceof Conditions){
Conditions<String,Object> map = (Conditions)param;
for(String key : map.keySet())
{
whereSQL.append(" and "+key + " = '" + map.get(key)+"',");
}
sql.append(whereSQL.subSequence(0,whereSQL.length()-1));
}
}
if(whereSQL.equals(" where 1=1 ")){
throw new RuntimeException("实体变量没有设置ID字段值");
}
return sql.toString();
}
private static MapperSqlHelper App(){
return new MapperSqlHelper();
}
public static String getExecuSQL(Class<?> clazz, String mapperDBsql,Object param) {
if(mapperDBsql.equals("MapperGD.find.entitys")){
return MapperSqlHelper.App().findEntityAll(clazz,param,false);//条件查询实体列表
}else if(mapperDBsql.equals("MapperGD.find.entityById")){
return MapperSqlHelper.App().findEntityById(clazz);//id查询实体
}else if(mapperDBsql.equals("MapperGD.find.ListByLike")){
return MapperSqlHelper.App().findEntityAll(clazz,param,true);//条件查询实体列表
}else if(mapperDBsql.equals("MapperGD.insert.entity")){
return MapperSqlHelper.App().insertEntity(clazz);//保存单一实体
}else if(mapperDBsql.equals("MapperGD.update.entity")){
return MapperSqlHelper.App().updateEntityById(clazz);//保存单一实体
}else if(mapperDBsql.equals("MapperGD.update.entity.condistion")){
return mapperDBsql;
}else if(mapperDBsql.equals("MapperGD.delete.id")){
return MapperSqlHelper.App().deleteById(clazz);
}else if(mapperDBsql.equals("MapperGD.delete.condition")){
return MapperSqlHelper.App().deleteByCondition(clazz,param);
}else if(mapperDBsql.equals("MapperGD.count.condition")){
return MapperSqlHelper.App().count(clazz,param);
}else if(mapperDBsql.equals("MapperGD.find.entity.queryByVo")){
return MapperSqlHelper.App().queryByVo(clazz,param,false);
}else if(mapperDBsql.equals("MapperGD.find.entity.queryByVoLike")){
return MapperSqlHelper.App().queryByVo(clazz,param,true);
}
return null;
}
//预留接口
private String updateEntityByConditions(Class<?> clazz,Object param){ return null;
}
public void getParam(Object param){
StringBuffer bf = new StringBuffer();
if (isPrimitiveType(param.getClass())) {
bf.append(param);
} else if (param instanceof Map) {
Map<String,Object> map = (Map)param;
}
} public static boolean isPrimitiveType(Class clazz) {
return clazz != null && (clazz.isPrimitive() || clazz.equals(Long.class) || clazz.equals(Integer.class)
|| clazz.equals(Short.class) || clazz.equals(Byte.class) || clazz.equals(Double.class)
|| clazz.equals(Float.class) || clazz.equals(Boolean.class) || clazz.equals(Character.class) || clazz.equals(String.class));
}
public static void main(String[] args) {
// Object object = null;
// if (isPrimitiveType(object.getClass())) {
// } else if (object instanceof Map) {
// }
Field[] files = User.class.getDeclaredFields();
User u = new User();
try {
System.out.println(FieldUtils.readDeclaredField(u, "id",true));
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试用例:
业务dao,这个接口继承自 IGenericDao
package org.cf.guott.mybatis.mapper; import java.util.List;
import java.util.Map; import org.apache.ibatis.annotations.Select;
import org.cf.guott.mybatis.ITestGDAO;
import org.cf.guott.mybatis.annotation.MyBatisRepository;
import org.cf.guott.mybatis.entity.User;
import org.cf.guott.mybatis.pagination.PageMyBatis; @MyBatisRepository(User.class)
public interface UserMapper extends IGenericDao<User,Integer>{ }
main运行方法
package org.cf.guott.mybatis.main; import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.ibatis.session.RowBounds;
import org.cf.guott.mybatis.entity.User;
import org.cf.guott.mybatis.helpers.Conditions;
import org.cf.guott.mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component; @Component
public class Main {
@Autowired
UserMapper userMapper;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-mybatis.xml");
Main main = context.getBean(Main.class);
Map map = new HashMap();
map.put("name", "ccc");
List<User> users = main.userMapper.LikequeryByVo(0,2,new Conditions<String, Object>().add("name", "guotiantdddian").addOrderBy("id").setSortByDesc());
System.out.println(users.size());
}
}
mybatis通用DAO的更多相关文章
- spring+mybatis通用dao层、service层的实现
个人理解: 1.mybatis-spring.jar 提供了SqlSessionTemplate类该类可以对数据库进行CRUD操作(底层其实还是SqlSession) 2.我们可以集成SqlSessi ...
- 使用mybatis完成通用dao和通用service
使用mybatis完成通用dao和通用service 概述: 使用通用dao和通用service可以减少代码的开发.可以将常用的增删改查放到通用dao中.对不同的or框架,基本上都有自己的实现如Spr ...
- Mybatis整合通用Dao,Mybatis整合通用Mapper,MyBatis3.x整合通用 Mapper3.5.x
Mybatis整合通用Dao,Mybatis整合通用Mapper,MyBatis3.x整合通用 Mapper3.5.x ============================== 蕃薯耀 2018年 ...
- Mybatis 使用PageHelper封装通用Dao分页方法
参考: PageHelper官网:https://pagehelper.github.io/docs/howtouse/#3-%E5%A6%82%E4%BD%95%E5%9C%A8%E4%BB%A3% ...
- Spring Boot MyBatis 通用Mapper插件集成
Mybatis在使用过程中需要三个东西,每张表对应一个XXMapper.java接口文件,每张表对应一个XXMapper.xml文件,每张表对应一个Entity的Java文件. 其中XXMappe ...
- mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类
相信大家在刚开始学习mybatis注解方式,或者spring+mybatis注解方式的时候,一定会有一个疑问,为什么mybatis的dao接口只需要一个接口,不需要实现类,就可以正常使用,笔者最开始的 ...
- spring基于通用Dao的多数据源配置详解【ds1】
spring基于通用Dao的多数据源配置详解 有时候在一个项目中会连接多个数据库,需要在spring中配置多个数据源,最近就遇到了这个问题,由于我的项目之前是基于通用Dao的,配置的时候问题不断,这种 ...
- SpringBoot 3.SpringBoot 整合 MyBatis 逆向工程以及 MyBatis 通用 Mapper
一.添加所需依赖,当前完整的pom文件如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&qu ...
- spring基于通用Dao的多数据源配置
有时候在一个项目中会连接多个数据库,须要在spring中配置多个数据源,近期就遇到了这个问题,因为我的项目之前是基于通用Dao的,配置的时候问题不断.这样的方式和资源文件冲突:扫描映射文件的话,Sql ...
随机推荐
- ZOJ 38727(贪心)
这道题真心坑.越想越远 想的飞起来了. 最后纠结起后缀表达式的定义来了. 题意: 就是给你一个串 , 让你用最少改动次数来实它变成一个合法的后缀表达式, 改动方式有两种, 一种是直接加入数字或者 ...
- Android使用ViewFlipper实现左右滑动效果面
在我的博客中,上次是使用ViewPager实现左右滑动的效果的,请看文章:Android使用ViewPager实现左右滑动效果. 这次我来使用ViewFlipper实现这种效果,好了,先看看效果吧: ...
- [Ext JS 4] 布局之实战一 - 中间区块不会自动伸展 (tab)
前言 [Ext JS 4] 布局之实战一 - 中间区块不会自动伸展 (tab) 在上一篇中,中间的tab 区块无法自动伸展的原因一句话说就是: 使用contentEL的方式,相关HTML元素不会参与组 ...
- Bzoj2034 2009国家集训队试题 最大收益 贪心+各种优化+二分图
这个题真的是太神了... 从一開始枚举到最后n方的转化,各种优化基本都用到了极致.... FQW的题解写了好多,个人感觉我全然没有在这里废话的必要了 直接看这里 各种方法真的是应有尽有 大概说下 首先 ...
- CSS小tip整理
CSS小tip整理 1.利用css在列表靠头和末尾添加箭头: /* 左箭头*/ ol a[rel="prev"]:before { content: "\00AB&quo ...
- 全国三级城市联动 js版
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 当前项目与当前环境的JDK版本不匹配”Bad version number in .class file“
java.lang.UnsupportedClassVersionError: Bad version number in .class file at java.lang.ClassLoader.d ...
- USACO Section 5.3 Milk Measuring (IDDFS+dp)
迭代加深搜索,从小到大枚举桶数的上限maxd:对每个maxd,枚举每个组合,判断是否能够倒出q:直到得到answer.判断的部分就用dp(完全背包). ------------------------ ...
- 关于php支持的协议与封装协议
<?php /* * php://stdin 标准输入流 * php://stdout 标准输入流 * php://stderr 标准错误流 * php://output 只写的数据流 * ph ...
- A Byte of Python 笔记(5)函数:定义、形参、局部变量、默认参数、关键参数
第7章 函数 函数是重要的程序段.它们允许你给一块语句一个名称,然后你可以在程序的任何地方使用这个名称任意多次地运行这个语句块.这被称为 调用 函数. 定义函数 函数通过 def 关键字定义.def ...