iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么开发一个MyBatis通用Mapper的轮子
  • 539
分享到

怎么开发一个MyBatis通用Mapper的轮子

2023-07-04 20:07:49 539人浏览 独家记忆
摘要

本篇内容介绍了“怎么开发一个mybatis通用Mapper的轮子”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!需求通用Mapper起码应该包

本篇内容介绍了“怎么开发一个mybatis通用Mapper的轮子”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    需求

    通用Mapper起码应该包含以下功能:

    批量增

    批量删

    只更新指定字段

    分页查询查当前页

    分页查询查总数

    字典字段翻译

    数据权限控制

    大概长下面这个样子: 

    public interface BaseMapper<T,K> {    int insert(T t);    int batchInsert(List<T> entity);        int deleteById(K id);        int deleteBatchIds(Collection<K> ids);        int updateById(T entity);        int updateSelectiveById(T entity);        T selectById(K id);        List<T> selectBatchIds(Collection<K> ids);        List<T> selectAll();        List<T> selectPage(PageRequest<T> pageRequest);        Long selectCount(T entity);}

    实现原理

    1、基于MyBatis3提供的SqlProvider构建动态Sql

    怎么开发一个MyBatis通用Mapper的轮子

    例如如下代码:

    @SelectProvider(type = UsersqlBuilder.class, method = "buildGetUsersByName")List<User> getUsersByName(String name);class UserSqlBuilder {  public static String buildGetUsersByName(final String name) {    return new SQL(){{      SELECT("*");      FROM("users");      if (name != null) {        WHERE("name like #{value} || '%'");      }      ORDER_BY("id");    }}.toString();  }}

    2、基于自定义注解,为实体和数据库表建立对应关系

    例如如下代码:

    @Table("user")public class User {    @Id(auto = true)    @Column(value = "id")    private Long id;    @Column(value = "name", filterOperator = FilterOperator.LIKE)    @OrderBy(orderPriority = 0)    private String name;    @OrderBy(order = Order.DESC, orderPriority = 1)    private Integer age;    private String email;    @Transient    private String test;}

    基于以上两个原理,当方法被调用时,我们便可构建出相应的动态Sql,从而实现该通用Mapper。

    代码实现

    1、自定义注解

    1)@Table

    了解Jpa的朋友一定很熟悉,这个就是为实体指定表名,实体不加这个注解就认为实体名与表名一致:

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface Table {    //表名,不指定则使用实体类名    String value() default "";}

    2)@Column

    指定完表名,该指定列名了,同样的如果字段不指定则认为字段名与表列名一致:

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Column {    //对应数据库列名    String value() default "";    //查询时的过滤类型    FilterOperator filterOperator() default FilterOperator.EQ;    //是否查询,select是否带上该字段    boolean selectable() default true;    //是否插入,insert是否带上该字段    boolean insertable() default true;    //是否更新,update是否带上该字段    boolean updatable() default true;}

    3)@Id

    这个注解就是为了表明该字段是否是数据库主键。当然,这个注解可以与@Column合并,但为了更清晰,我还是决定单独使用这个注解。并且,也方便后期扩展。

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Id {    //主键是否自动生成    boolean auto() default false;}

    4)@OrderBy

    这个注解来标明查询时的排序字段,同时考虑如果排序字段有多个,可定义优先级:

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface OrderBy {    //排序    Order order() default Order.ASC;    //多个排序字段先后顺序    int orderPriority() default 0;}

    5)@Transient

    考虑实体中有些字段在数据库中不存在的情况。使用这个注解来标注这样的字段:

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Transient {}

    2、几个pojo,用来保存实体对应的信息

    1)TableInfo,表示一个实体对应的数据库表信息

    public class TableInfo {    //表对应的实体类型    private Class<?> entityClass;    //表名    private String tableName;    //列    private List<ColumnInfo> columns;    //是否联合主键    private boolean isUNIOnId;}

    2)ColumnInfo,表示实体中的一个字段对应的数据库表字段信息

    public class ColumnInfo {    //对应的java类型    private Class<?> fieldClass;    private Field field;    private FilterOperator filterOperator;    //数据库列    private String column;    //是否主键    private boolean isPrimaryKey;    //主键填充方式    private boolean isPrimaryKeyAuto;    //排序    private Order orderBy;    private int orderByPriority;    //是否参与insert    private boolean insertable;    //是否参与update    private boolean updatable;    //是否参与select    private boolean selectable;}

    以上只需要注意一点,如何判断一个实体是否是联合主键。这里用的比较粗暴的方法,如果有多个字段加了@Id,那么认为是联合主键。

    3、定义开头说的BaseMapper

    这个BaseMapper的定义模仿了springDataJpa,它需要两个泛型,T表示实体类型,K表示主键类型。

    一般情况下K为简单数据类型,比如Long,String;

    联合主键情况下,K为自定义的一个复杂数据类型,具体使用方法见文章最后章节。

    public interface BaseMapper<T,K> {    @InsertProvider(type = SqlProvider.class,method = "insert")    @Options(useGeneratedKeys = true, keyProperty = "id",keyColumn = "id")    int insert(T t);    @InsertProvider(type = SqlProvider.class,method = "batchInsert")    int batchInsert(@Param("list") List<T> entity);    @DeleteProvider(type = SqlProvider.class,method = "deleteById")    int deleteById(@Param("id") K id);    @DeleteProvider(type = SqlProvider.class,method = "deleteBatchIds")    int deleteBatchIds(@Param("ids") Collection<K> ids);    @UpdateProvider(type = SqlProvider.class,method = "updateById")    int updateById(T entity);    @UpdateProvider(type = SqlProvider.class,method = "updateSelectiveById")    int updateSelectiveById(T entity);    @SelectProvider(type = SqlProvider.class,method = "selectById")    T selectById(@Param("id") K id);    @SelectProvider(type = SqlProvider.class,method = "selectBatchIds")    List<T> selectBatchIds(@Param("ids") Collection<K> ids);    @SelectProvider(type = SqlProvider.class,method = "selectAll")    List<T> selectAll();    @SelectProvider(type = SqlProvider.class,method = "selectPage")    List<T> selectPage(PageRequest<T> pageRequest);    @SelectProvider(type = SqlProvider.class,method = "selectCount")    Long selectCount(T entity);}

    4、SqlProvider

    public class SqlProvider<T> {    private static Logger logger = LoggerFactory.getLogger(SqlProvider.class);    private static Map<Class<?>, TableInfo> tableCache = new ConcurrentHashMap<>();    public String insert(T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        String intoColumns = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isInsertable)                .map(ColumnInfo::getColumn)                .collect(Collectors.joining(","));        String values = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isInsertable)                .map(ColumnInfo::variable)                .collect(Collectors.joining(","));        String sql = new SQL()                .INSERT_INTO(tableName)                .INTO_COLUMNS(intoColumns)                .INTO_VALUES(values).toString();        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String batchInsert(@Param("list" ) List<?> entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        String intoColumns = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isInsertable)                .map(ColumnInfo::getColumn)                .collect(Collectors.joining(","));        String values = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isInsertable)                .map(column->column.variableWithPrefix("item"))                .collect(Collectors.joining(","));        String sql = new SQL()                .INSERT_INTO(tableName)                .INTO_COLUMNS(intoColumns).toString();        sql += " values ";        sql += "<foreach collection=\"list\" item=\"item\" separator=\",\">" +                "  <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">" +                "    " + values +                "  </trim>" +                "</foreach>";        sql = "<script>"+sql+"</script>";        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String deleteById(@Param("id") T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        String[] where = null;        if (tableInfo.isUnionId()){            where = tableInfo.getColumns()                    .stream()                    .filter(ColumnInfo::isPrimaryKey)                    .map(columnInfo -> columnInfo.getColumn()+" = #{id."+columnInfo.getField().getName()+"}")                    .toArray(String[]::new);        }else {            where = tableInfo.getColumns()                    .stream()                    .filter(ColumnInfo::isPrimaryKey)                    .map(columnInfo -> columnInfo.getColumn()+" = #{id}")                    .toArray(String[]::new);        }        String sql = new SQL()                .DELETE_FROM(tableName)                .WHERE(where)                .toString();        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String deleteBatchIds(@Param("ids") Collection<?> entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        if (tableInfo.isUnionId()){            String[] where = new String[entity.size()];            for (int i = 0; i < entity.size(); i++){                List<String> list = new ArrayList<>();                String s = "%s=#{ids[%d].%s}";                for (ColumnInfo columnInfo:tableInfo.getColumns()){                    if (columnInfo.isPrimaryKey()){                        list.add(String.fORMat(s,columnInfo.getColumn(),i,columnInfo.getField().getName()));                    }                }                where[i] = "("+StringUtils.join(list," and ")+")";            }            String sql = "delete from %s where %s ";            sql = String.format(sql,tableName,StringUtils.join(where," or "));            logger.info("sql->{},params->{}",sql,entity);            return sql;        }else {            String idName = tableInfo.getColumns()                    .stream()                    .filter(ColumnInfo::isPrimaryKey)                    .findFirst()                    .get()                    .getColumn();            String sql = "DELETE FROM %s WHERE %s IN (%s) ";            String[] arr = new String[entity.size()];            for (int i = 0; i < entity.size(); i++){                arr[i] = "#{ids["+i+"]}";            }            sql = String.format(sql,tableName,idName,StringUtils.join(arr,","));            logger.info("sql->{},params->{}",sql,entity);            return sql;        }    }    public String updateById(T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        String[] where = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isPrimaryKey)                .map(columnInfo -> columnInfo.getColumn()+" = "+columnInfo.variable())                .toArray(String[]::new);        String sql = new SQL().UPDATE(tableName).SET(tableInfo.updateSetColumn()).WHERE(where).toString();        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String updateSelectiveById(T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        String[] where = tableInfo.getColumns()                .stream()                .filter(ColumnInfo::isPrimaryKey)                .map(columnInfo -> columnInfo.getColumn()+" = "+columnInfo.variable())                .toArray(String[]::new);        String sql = new SQL().UPDATE(tableName).SET(tableInfo.updateSetSelectiveColumn(entity)).WHERE(where).toString();        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String selectById(@Param("id")T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String[] where = null;        if (tableInfo.isUnionId()){            where = tableInfo.getColumns().stream().filter(ColumnInfo::isPrimaryKey)                    .map(columnInfo -> columnInfo.getColumn()+" = #{id."+columnInfo.getField().getName()+"}")                    .toArray(String[]::new);        }else {            where = tableInfo.getColumns().stream().filter(ColumnInfo::isPrimaryKey)                    .map(columnInfo -> columnInfo.getColumn()+" = #{id}")                    .toArray(String[]::new);        }        String sql = new SQL()                .SELECT(tableInfo.selectColumnAsProperty())                .FROM(tableInfo.getTableName())                .WHERE(where)                .toString();        logger.info("sql->{},params->{}",sql,entity);        return sql;    }    public String selectBatchIds(@Param("ids")Collection<?> entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        String tableName = tableInfo.getTableName();        if (tableInfo.isUnionId()){            String[] where = new String[entity.size()];            for (int i = 0; i < entity.size(); i++){                List<String> list = new ArrayList<>();                String s = "%s=#{ids[%d].%s}";                for (ColumnInfo columnInfo:tableInfo.getColumns()){                    if (columnInfo.isPrimaryKey()){                        list.add(String.format(s,columnInfo.getColumn(),i,columnInfo.getField().getName()));                    }                }                where[i] = "("+StringUtils.join(list," and ")+")";            }            String sql = "select %s from %s where %s";            sql = String.format(sql,tableInfo.selectColumnAsProperty(),tableInfo.getTableName(),StringUtils.join(where," or "));            logger.info("sql->{},params->{}",sql,entity);            return sql;        }else {            String idName = tableInfo.getColumns()                    .stream()                    .filter(ColumnInfo::isPrimaryKey)                    .findFirst()                    .get()                    .getColumn();            String sql = "select %s from %s where %s in (%s) ";            String[] arr = new String[entity.size()];            for (int i = 0; i < entity.size(); i++){                arr[i] = "#{ids["+i+"]}";            }            sql = String.format(sql,tableInfo.selectColumnAsProperty(),tableName,idName,StringUtils.join(arr,","));            logger.info("sql->{},params->{}",sql,entity);            return sql;        }    }    public String selectAll(T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        SQL sql =  new SQL()                .SELECT(tableInfo.selectColumnAsProperty())                .FROM(tableInfo.getTableName());        String orderBy = tableInfo.orderByColumn();        if (StringUtils.isNotEmpty(orderBy)){            sql.ORDER_BY(orderBy);        }        return sql.toString();    }    public String selectPage(PageRequest<T> entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        SQL sql = new SQL()                .SELECT(tableInfo.selectColumnAsProperty())                .FROM(tableInfo.getTableName());        String[] where = tableInfo.getColumns().stream()                .filter(column -> {                    Field field = column.getField();                    T bean = entity.getPageParams();                    Object value = Util.getFieldValue(bean, field);                    if (value == null) {                        return false;                    }                    return StringUtils.isNotEmpty(value.toString());                })                .map(column -> {                    String param = " #{pageParams." + column.getField().getName()+"}";                    if (column.getFilterOperator() == FilterOperator.LIKE){                        param = "concat('%', "+param+", '%')";                    }                    if (column.getFilterOperator() == FilterOperator.LEFTLIKE){                        param = "concat("+param+", '%')";                    }                    if (column.getFilterOperator() == FilterOperator.RIGHTLIKE){                        param = "concat('%', "+param+")";                    }                    return column.getColumn()+column.filterOperator()+param;                })                .toArray(String[]::new);        sql.WHERE(where);        if (StringUtils.isNotEmpty(entity.getOrder())){            ColumnInfo columnInfo = tableInfo.getColumns().stream()                    .filter(columnInfo1 -> columnInfo1.getField().getName().equalsIgnoreCase(entity.getOrder()))                    .findFirst().orElse(null);            if (columnInfo != null){                String direction = entity.getOrderDirection();                direction = (StringUtils.isEmpty(direction) || direction.equalsIgnoreCase("asc"))?" asc ":" desc ";                sql.ORDER_BY(columnInfo.getColumn() + direction);            }        }else {            String orderBy = tableInfo.orderByColumn();            if (StringUtils.isNotEmpty(orderBy)){                sql.ORDER_BY(orderBy);            }        }        sql.OFFSET("#{offset}").LIMIT("#{pageSize}");        String s = sql.toString();        logger.info("sql->{},params->{}",s,entity);        return s;    }    public String selectCount(T entity, ProviderContext context){        TableInfo tableInfo = getTableInfo(context);        SQL sql = new SQL()                .SELECT("count(1)")                .FROM(tableInfo.getTableName());        String[] where = tableInfo.getColumns().stream()                .filter(column -> {                    Field field = column.getField();                    Object value = Util.getFieldValue(entity, field);                    if (value == null) {                        return false;                    }                    return StringUtils.isNotEmpty(value.toString());                })                .map(column -> {                    String param = " #{" + column.getField().getName()+"}";                    if (column.getFilterOperator() == FilterOperator.LIKE){                        param = "concat('%', "+param+", '%')";                    }                    if (column.getFilterOperator() == FilterOperator.LEFTLIKE){                        param = "concat("+param+", '%')";                    }                    if (column.getFilterOperator() == FilterOperator.RIGHTLIKE){                        param = "concat('%', "+param+")";                    }                    return column.getColumn()+column.filterOperator()+param;                })                .toArray(String[]::new);        sql.WHERE(where);        String s = sql.toString();        logger.info("sql->{},params->{}",s,entity);        return s;    }    private TableInfo getTableInfo(ProviderContext context){        Class<?> clz = getEntityType(context);        return tableCache.computeIfAbsent(context.getMapperType(), t-> Util.tableInfo(clz));    }    private Class<?> getEntityType(ProviderContext context) {        return Stream.of(context.getMapperType().getGenericInterfaces())                .filter(ParameterizedType.class::isInstance)                .map(ParameterizedType.class::cast)                .filter(type -> type.getRawType() == BaseMapper.class)                .findFirst()                .map(type -> type.getActualTypeArguments()[0])                .filter(Class.class::isInstance)                .map(Class.class::cast)                .orElseThrow(() -> new IllegalStateException("未找到BaseMapper的泛型类 " + context.getMapperType().getName() + "."));    }}

    5、实体类转TableInfo

    public static TableInfo tableInfo(Class<?> entityClass) {        TableInfo info = new TableInfo();        info.setEntityClass(entityClass);        Table table = entityClass.getAnnotation(Table.class);        String tableName = entityClass.getSimpleName();        if (table != null && StringUtils.isNotEmpty(table.value())){            tableName = table.value();        }        info.setTableName(tableName);        Field[] allFields = getFields(entityClass);        Field[] fields = Stream.of(allFields)                //过滤@Transient注解的field                .filter(field -> !field.isAnnotationPresent(Transient.class))                .toArray(Field[]::new);        List<ColumnInfo> columns = new ArrayList<>();        int idCount = 0;        for (Field field:fields){            ColumnInfo columnInfo = new ColumnInfo();            columnInfo.setFieldClass(field.getDeclarinGClass());            columnInfo.setField(field);            Id id = field.getAnnotation(Id.class);            idCount = idCount + (id == null?0:1);            columnInfo.setPrimaryKey(id == null?Boolean.FALSE:Boolean.TRUE);            columnInfo.setPrimaryKeyAuto(id == null?Boolean.FALSE:id.auto());            Column column = field.getAnnotation(Column.class);            String columnName = field.getName();            if (column != null && StringUtils.isNotEmpty(column.value())){                columnName = column.value();            }            columnInfo.setColumn(columnName);            FilterOperator filterOperator = FilterOperator.EQ;            if (column != null && column.filterOperator() != null){                filterOperator = column.filterOperator();            }            columnInfo.setFilterOperator(filterOperator);            if (columnInfo.isPrimaryKeyAuto()){                columnInfo.setInsertable(false);            }else {                columnInfo.setInsertable(true);                if (column != null){                    columnInfo.setInsertable(column.insertable());                }            }            columnInfo.setUpdatable(true);            columnInfo.setSelectable(true);            if (column != null){                columnInfo.setSelectable(column.selectable());                columnInfo.setUpdatable(column.updatable());            }            OrderBy orderBy = field.getAnnotation(OrderBy.class);            if (orderBy != null){                columnInfo.setOrderBy(orderBy.order());                columnInfo.setOrderByPriority(orderBy.orderPriority());            }            columns.add(columnInfo);        }        if (idCount > 1){            info.setUnionId(Boolean.TRUE);        }        info.setColumns(columns);        return info;    }

    6、字典字段自动翻译

    简单实现思路:对需要翻译的字段加上@FieldTrans注解来表明这个字段需要翻译,通过aop方式对结果数据进行增强,来将字段进行翻译更新。

    此部分内容留待后续实现,同时调研一下是否还有更优雅简单的实现方式。

    7、数据权限

    我们先来思考一下数据权限到底要干啥?一句话来概括:查一张表的数据时在where条件中追加“and 控制权限的列 in (???)”。

    简单实现方法:在控制权限的字段加上@DataAuthrity注解来表明通过这个字段控制权限,而???的内容肯定是由业务代码来生成的,因此考虑给这个注解增加一个属性,用来指明权限数据由执行哪个接口或方法来获取。

    此部分内容留待后续实现,同时调研一下是否还有更优雅简单的实现方式。

    使用示例

    1、数据库表

    CREATE TABLE `user` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `name` varchar(255) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  `email` varchar(255) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

    2、实体

    @Table("user")public class User {    @Id(auto = true)    @Column(value = "id")    private Long id;    @Column(value = "name", filterOperator = FilterOperator.LIKE)    @OrderBy(orderPriority = 0)    private String name;    @OrderBy(order = Order.DESC, orderPriority = 1)    private Integer age;    private String email;    @Transient    private String test;}

    3、Mapper

    public interface UserMapper extends BaseMapper<User, Long> {}

    至此,不需要写任何mapper.xml,UserMapper已经具备了增删改查能力。

    4、联合主键示例

    public class User1 {    @Id    @Column(value = "id1")    private String id1;        @Id    @Column(value = "id2")    private String id2;        @Column(value = "name", filterOperator = FilterOperator.LIKE)    @OrderBy(orderPriority = 0)    private String name;        @OrderBy(order = Order.DESC, orderPriority = 1)    private Integer age;        private String email;        @Transient    private String test;}public class User1Id {    private String id1;    private String id2;}public interface User1Mapper extends BaseMapper<User1,User1Id> {}

    “怎么开发一个MyBatis通用Mapper的轮子”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: 怎么开发一个MyBatis通用Mapper的轮子

    本文链接: https://www.lsjlt.com/news/347312.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • 怎么开发一个MyBatis通用Mapper的轮子
      本篇内容介绍了“怎么开发一个MyBatis通用Mapper的轮子”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!需求通用Mapper起码应该包...
      99+
      2023-07-04
    • 详解如何开发一个MyBatis通用Mapper的轮子
      目录一、前言二、需求三、实现原理四、代码实现1、自定义注解2、几个pojo,用来保存实体对应的信息3、定义开头说的BaseMapper4、SqlProvider5、实体类转Table...
      99+
      2022-12-21
      MyBatis通用Mapper轮子 MyBatis Mapper轮子 MyBatis Mapper
    • mybatis的mapper怎么使用
      MyBatis的mapper是用于映射数据库操作的接口,通过这个接口可以方便地调用SQL语句进行数据库的增删改查操作。使用步骤如下:...
      99+
      2023-09-29
      mybatis
    • java应用开发之Mybatis通过Mapper代理自定义接口的实现
      如何实现?主要分为以下两步骤 1.通过 Mapper 代理实现⾃定义接口 2.编写与方法相对应的 Mapper.xml 1.自定义接口Account...
      99+
      2024-04-02
    • 怎么使用Vue开发一个五子棋小游戏
      这篇文章主要讲解了“怎么使用Vue开发一个五子棋小游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Vue开发一个五子棋小游戏”吧!1.绘制游戏区域和游戏元素开始写代码之前,一定要记...
      99+
      2023-07-02
    • Mybatis中mapper的map方法怎么使用
      在MyBatis中,Mapper接口中的map方法是用来执行SQL语句并将结果映射到Java对象的。首先,在Mapper接口中定义一...
      99+
      2023-10-12
      Mybatis
    • Android开发中使用ViewPager实现一个轮翻图效果
      Android开发中使用ViewPager实现一个轮翻图效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体方法如下:import java.util.ArrayList...
      99+
      2023-05-31
      android viewpager age
    • 在Android开发中利用ViewPager实现一个轮播功能
      本篇文章给大家分享的是有关在Android开发中利用ViewPager实现一个轮播功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。ViewPager是一个常用的Android...
      99+
      2023-05-31
      viewpager android age
    • 怎么用vue写一个轮播图
      本篇内容主要讲解“怎么用vue写一个轮播图”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用vue写一个轮播图”吧!1.先展示最终效果:2.解决思路Vue的理念是以数据驱动视图,所以拒绝通过改...
      99+
      2023-07-04
    • tk.mybatis怎么扩展自己的通用mapper
      小编给大家分享一下tk.mybatis怎么扩展自己的通用mapper,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!tk.mybatis扩展自己的通用mapper目的:tk.mybatis 提供的通用mapper,虽然使用方...
      99+
      2023-06-15
    • vscode中怎么开发一个vue应用
      今天就跟大家聊聊有关vscode中怎么开发一个vue应用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。从安装开始为了准确起见,我们把vscode里所...
      99+
      2024-04-02
    • Android开发中怎么实现一个沉浸式通知栏
      Android开发中怎么实现一个沉浸式通知栏?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。①DrawerLayout+Toolbar添加依赖库(谷歌提供)compile&nbs...
      99+
      2023-05-31
      android roi
    • 使用WebIDE怎么开发一个Android应用
      本篇文章给大家分享的是有关使用WebIDE怎么开发一个Android应用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C4C里做Android开发用的是Google的Andro...
      99+
      2023-06-04
    • 使用Python怎么开发一个个人云盘应用
      本篇文章为大家展示了使用Python怎么开发一个个人云盘应用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python的数据类型有哪些python的数据类型:1. 数字类型,包括int(整型)、lo...
      99+
      2023-06-14
    • 怎么使用CSS绘制一个可爱卡通狮子动画
      这篇文章主要介绍了怎么使用CSS绘制一个可爱卡通狮子动画的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用CSS绘制一个可爱卡通狮子动画文章都会有所收获,下面我们一起来看看...
      99+
      2024-04-02
    • Mybatis中的mapper模糊查询语句LIKE怎么使用
      本篇内容介绍了“Mybatis中的mapper模糊查询语句LIKE怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Mybatis ma...
      99+
      2023-06-21
    • 如何使用MongoDB开发一个简单的电子商务网站
      如何使用MongoDB开发一个简单的电子商务网站作为一种流行的非关系型数据库,MongoDB在电子商务网站的开发中具有很大的优势。它的可伸缩性和灵活性使得它成为构建强大而且易于扩展的电子商务网站的理想选择。本文将向您介绍如何使用MongoD...
      99+
      2023-10-22
      开发 电子商务 MongoDB
    • 通过一个例子学习Kubernetes里的PersistentVolumeClaim的用法
      Kubernetes的pod本身是无状态的(stateless),生命周期通常比较短,只要出现了异常,Kubernetes就会自动创建一个新的Pod来代替它。而容器产生的数据,会随着Pod消亡而自动消失。为了实现Pod内数据的存储管理,Ku...
      99+
      2023-06-04
    • 使用SpringMVC和MyBatis框架如何搭建一个开发环境
      本篇文章给大家分享的是有关使用SpringMVC和MyBatis框架如何搭建一个开发环境,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。下载SpringMVC框架架包,点击打开地...
      99+
      2023-05-31
      springmvc sprinmybatis 环境搭建
    • 微信开发中如何使用springmvc 搭建一个mybatis项目
      本篇文章为大家展示了微信开发中如何使用springmvc 搭建一个mybatis项目,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。①在建立好的maven项目中的pom.xml文件引入依赖,代码如下:...
      99+
      2023-05-31
      springmvc mybatis
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作