Mybatis实现动态增删改查功能的示例代码

一、Mybatis 流程简介

最近在看 Mybatis 的源码,大致了解整个框架流程后便手写了一个特别简单的SimpMybatis的小Demo,来巩固这整个框架的学习。下图是我所画的框架大致执行流程:

💊对上图分析后得出结论:

1.Mybatis 的配置文件分为两种,且这两个配置文件会被封装到 Configuration 中

  • 主配置文件(MybatisConfig.xml):配置 jdbc 等环境信息,全局唯一;
  • 映射文件(xxxMapper.xml):配置多个 Sql ,可有多个。

2.通过 Mybatis 配置文件得到 SqlSessionFactory ;
3.通过 SqlSessionFactory 得到 SqlSession,它就相当于 Request 请求;
4.SqlSession 调用底层的 Executor 执行器来操作数据库,同时执行器有两类实现

  • 基本实现
  • 带有缓存功能的实现

5.解析传入的参数,对其进行封装,执行并返回结果;
以上就是我梳理的 Mybatis 大致流程,看似简单,却很精妙。

二、手写简化版 Mybatis 设计思路

2.1 简化后的思路

2.2 读取 XML 文件,建立连接

从图中可以看出,MyConfig 负责与人交互。待读取xml后,将属性和连接数据库的操作封装在 MyConfig 对象中供后面的组件调用。本项目将使用 dom4j 来读取xml文件,它具有性能优异和非常方便使用的特点。

2.3 创建SqlSession,搭建 Configuration 和 Executor 之间的桥梁

从流程图中的箭头可以看出,MySqlSession 的成员变量中必须得有 MyExecutorImpl 和 MyConfig 去集中做调配。一个Session仅拥有一个对应的数据库连接。类似于一个前段请求Request,它负责直接调用对应 execute(sql) 来做 CRUD 操作。

2.4 创建 MyExecutor,封装 JDBC 操作数据库

MyExecutor 是一个执行器,负责SQL语句的生成和查询缓存的维护,也就是 Jdbc 的代码将在这里完成,不过本文只实现了单表,查询缓存并未实现。

2.5 创建 MySqlSessionProxy,使用动态代理生成 Mapper 对象

只是希望对指定的接口生成一个对象,使得执行它的时候能运行一句 sql,而接口无法直接调用方法,所以这里使用动态代理生成对象,在执行时还是回到 MySqlSession 中调用查询,最终由 MyExecutorImpl 做 JDBC查询。这样设计是为了单一职责,可扩展性更强。

三、实现自己的Mybatis

这次会将其打成 Jar 包,并将其导入项目实现,做一个 Mybatis 的还原。

工程文件及目录:

3.1 导入两个所需 Jar 包:数据库连接和XML解析

Maven 导入如下:

<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- xml解析 -->
<dependency>
 <groupId>org.dom4j</groupId>
 <artifactId>dom4j</artifactId>
 <version>2.1.3</version>
</dependency>

<!-- Mysql -->
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.49</version>
</dependency>

3.2 创建 MyConfig 类,对两大 XML 配置文件进行解析,并建立连接

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:17
 */
public class MyConfig {
 /**
  * 启动应用程序类加载器
  */
 private static final ClassLoader loader = ClassLoader.getSystemClassLoader();
 /**
  * 数据库建立连接
  * @return 返回数据库连接对象
  *
  */
 public Connection build() {

  // Mybatis主配置文件名
  String resource = "mybatis-config.xml";

  // 获取文件根节点
  Element root = parseXML(resource);
  // 获取文件对应的信息
  Map<String, String> jdbcMap = parseNodes(root);
  try {
   Class.forName(jdbcMap.get("driverClassName"));
  } catch (ClassNotFoundException e) {
   throw new RuntimeException("驱动器未找到,请重新检查!");
  }
  Connection connect = null;
  try {
   connect = DriverManager.getConnection(jdbcMap.get("url"), jdbcMap.get("username"), jdbcMap.get("password"));
  } catch (SQLException throwables) {
   throw new RuntimeException("数据库连接错误,请检查路径、用户名、密码是否输入正确!");
  }
  return connect;
 }
 /**
  * 解析数据库配置文件
  * @param resource 数据库配置文件路径
  * @return 获取到的文件根节点
  */
 public static Element parseXML(String resource) {
  try {
   // 返回用于读取指定资源的输入流
   InputStream stream = loader.getResourceAsStream(resource);
   // 使用dom4j解析XML
   SAXReader reader = new SAXReader();
   // 使用SAX从给定流中读取文件
   Document doc = reader.read(stream);
   // 获取文件的根节点
   return doc.getRootElement();
  } catch (DocumentException e) {
   throw new RuntimeException("解析 XML 时发生错误!" + resource);
  }
 }
 /**
  * 解析主xml文件标签节点
  * @param node 配置文件根节点
  * @return 返回从配置文件中拿到的开启数据库对应值
  */
 private Map<String, String> parseNodes(Element node) {
  // 判断根标签名称
  if (!node.getName().equals("database")) {
   throw new RuntimeException("数据库配置文件根标签名称必须为【database】");
  }

  // 存放配置文件取得的值
  Map<String, String> map = new HashMap<String, String>();
  map.put("driverClassName", null);
  map.put("url", null);
  map.put("username", null);
  map.put("password", null);

  // 读取property的属性内容
  for (Element item : node.elements()) {
   // 获取标签中存放的值,并删除其前导和结尾的空格
   String value = getValue(item);
   // 获取标签中 name 的名称
   String name = item.attributeValue("name");
   // 如果name或value为空则有对应值未输入
   if (name == null || "".equals(value)) {
    throw new RuntimeException("[database]: <property> 中应该包含名称和值");
   }
   switch (name) {
    case "driverClassName" : map.put("driverClassName", value); break;
    case "url" : map.put("url", value); break;
    case "username" : map.put("username", value); break;
    case "password" : map.put("password", value); break;
    default: throw new RuntimeException("[database]: <property> 中有未知属性");
   }
  }
  return map;
 }
 /**
  * 获取property属性中的值
  * @param node 配置文件根节点
  * @return 如果有value值,则读取;没有设置value,则读取内容
  */
 private static String getValue(Element node) {
  return node.hasContent() ? node.getText().trim() : node.attributeValue("value").trim();
 }
 /**
  *
  * @param path
  * @return
  */
 @SuppressWarnings(value = "rawtypes")
 public MappingBean readMapper(String path) {
  MappingBean bean = new MappingBean();
  try {
   InputStream stream = loader.getResourceAsStream(path);
   SAXReader reader = new SAXReader();
   Document doc = reader.read(stream);
   Element root = doc.getRootElement();
   // 把mapper节点的nameSpace值存为接口名
   bean.setInterfaceName(root.attributeValue("nameSpace").trim());
   // 用来存储方法的List
   List<Mapping> list = new ArrayList<Mapping>();
   //遍历根节点下所有子节点
   for(Iterator rootIter = root.elementIterator(); rootIter.hasNext();) {
    // 存储一条方法的信息
    Mapping fun = new Mapping();
    Element e = (Element) rootIter.next();
    String sqlType = e.getName().trim();
    String funcName = e.attributeValue("id").trim();
    String sql = e.getText().trim();
    String resultType = e.attributeValue("resultType").trim();
    fun.setSqlType(sqlType);
    fun.setFuncName(funcName);
    Object newInstance = null;
    try {
     newInstance = Class.forName(resultType).newInstance();
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e1) {
     e1.printStackTrace();
    }
    fun.setResultType(newInstance);
    fun.setSql(sql);
    list.add(fun);
   }
   bean.setList(list);

  } catch (DocumentException e) {
   e.printStackTrace();
  }
  return bean;
 }
 /**
  * 解析mapper映射xml文件
  * @param element mapper文件路径
  * @return
  */
 public MappingBean parseMapper(Element element) {

  MappingBean bean = new MappingBean();
  String namespace = element.attributeValue("namespace");
  if (namespace == null) {
   throw new RuntimeException("映射文件namespace不存在");
  }
  bean.setInterfaceName(namespace);
  List<Mapping> list = new ArrayList<>();
  Iterator<Element> it = element.elementIterator();
  while (it.hasNext()) {
   Element ele=(Element) it.next();
   Mapping mapping =new Mapping();
   String funcName =ele.attributeValue("id");
   if (funcName==null){
    throw new RuntimeException("mapper映射文件中id不存在");
   }
   String sqlType = ele.getName();
   String paramType = ele.attributeValue("parameterType");
   String resultType=ele.attributeValue("resultType");
   String sql=ele.getText().trim();
   mapping.setFuncName(funcName);
   mapping.setSqlType(sqlType);
   mapping.setParameterType(paramType);
   mapping.setSql(sql);
   Object object=null;
   try {
    object=Class.forName(resultType).newInstance();
   } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
    e.printStackTrace();
   }
   mapping.setResultType(object);
   list.add(mapping);
  }
  bean.setList(list);
  return bean;
 }
}

⚡由 MyConfig类 代码可以得知:

  1. Mybatis 主配置类名称必须为:mybatis-config.xml
  2. mybatis-config.xml 的根标签必须为: <database></database>
  3. Mapper.xml 必须包括:namespace
  4. Sql 是否有返回值都应包括:resultType(个人偷懒,没做判断);... ...

3.3 MySqlSession 代理

MySqlSession 肯定不会自己去执行,因为不能写死所以使用动态代理来使代理类去实现具体方法。

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:52
 */
public class MySqlSession {
 private final MyExcutor excutor= new MyExcutorImpl();

 private final MyConfig config = new MyConfig();

 public <T> T selectValue(Mapping statement, List<Object> parameter){
  return excutor.queryValue(statement, parameter);
 }

 public <T> T selectNull(Mapping statement){
  return excutor.queryNull(statement);
 }

 public int deleteValue(Mapping statement, List<Object> parameter) {
  return excutor.deleteValue(statement, parameter);
 }

 public int updateValue(Mapping statement, List<Object> parameter) {
  return excutor.updateValue(statement, parameter);
 }

 public int insertValue(Mapping mapping, List<Object> parameter) {
  return excutor.insertValue(mapping, parameter);
 }

 @SuppressWarnings("unchecked")
 public <T> T getMapper(Class<T> clas){
  //动态代理调用
  return (T) Proxy.newProxyInstance(clas.getClassLoader(),new Class[]{clas},
    new MySqlSessionProxy(config,this));
 }
}

编写代理类,把mapper映射文件解析进来

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:55
 */
public class MySqlSessionProxy implements InvocationHandler {
 private MyConfig config;
 private MySqlSession sqlSession;

 public MySqlSessionProxy(MyConfig config, MySqlSession sqlSession) {
  this.config = config;
  this.sqlSession = sqlSession;
 }

 @Override
 public Object invoke(Object proxy, Method method,Object[] args) {
  String name = method.getDeclaringClass().getName();
  String mapperName = name.substring(name.lastIndexOf(".")+1);
  MappingBean bean=config.parseMapper(MyConfig.parseXML(mapperName+".xml"));

  if (bean!=null && (bean.getList()!=null && bean.getList().size()>0)){
   for (Mapping mapping : bean.getList()){
    if (mapping.getFuncName().equals(method.getName())) {
     // 判断是否为查询语句
     if ("select".equals(mapping.getSqlType().toLowerCase())) {
      System.out.println("执行查询方法:" + mapping.getSql());
      if (args!=null) {
       System.out.println("参数:"+ Arrays.toString(args));
       return sqlSession.selectValue(mapping, Arrays.asList(args));
      } else {
       System.out.println("参数:null");
       return sqlSession.selectNull(mapping);
      }
     }
     // 判断是否为删除语句
     if ("delete".equals(mapping.getSqlType().toLowerCase())){
      System.out.println("执行查询方法:"+mapping.getSql());
      System.out.println("参数:"+ Arrays.toString(args));
      return sqlSession.deleteValue(mapping, Arrays.asList(args));
     }
     // 判断是否为更新语句
     if ("update".equals(mapping.getSqlType().toLowerCase())) {
      System.out.println("执行查询方法:"+mapping.getSql());
      System.out.println("参数:"+ Arrays.toString(args));
      return sqlSession.updateValue(mapping, Arrays.asList(args));
     }
     // 判断是否为插入语句
     if ("insert".equals(mapping.getSqlType().toLowerCase())) {
      System.out.println("执行查询方法:" + mapping.getSql());
      System.out.println("参数:" + Arrays.toString(args));
      return sqlSession.insertValue(mapping, Arrays.asList(args));
     }
    }
   }
  }
  return null;
 }
}

⚡注意:通过上段代码可知,映射文件必须和接口名称保持一致。

3.4 创建对应实体类和XML映射文件Sql实体类

a. 接口实体类

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:38
 */
public class MappingBean {
 /**
  * 接口名
  */
 private String interfaceName;
 /**
  * 接口下所有方法
  */
 private List<Mapping> list;
 // setter、getter略
}

b. 映射文件中 Sql 的实体类

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:38
 */
public class Mapping {
 private String sqlType;
 private String funcName;
 private String sql;
 private Object resultType;
 private String parameterType;
  // setter、getter略
}

3.5 创建 MyExcutor 接口以及实现类

MyExcutor 接口

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:42
 */
public interface MyExcutor {
 // 无参查询
 <T> T queryNull(Mapping mapping);
	// 有参查询
 <T> T queryValue(Mapping mapping, List<Object> params);
	// 删除
 int deleteValue(Mapping mapping, List<Object> params);
	// 更新
 int updateValue(Mapping mapping, List<Object> params);
	// 插入
 int insertValue(Mapping mapping, List<Object> params);
}

MyExcutorImpl 实现类

这里通过反射将结果转换成对象

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:42
 */
public class MyExcutorImpl implements MyExcutor {

 private MyConfig config = new MyConfig();

 @Override
 public <T> T queryNull(Mapping mapping) {
  Connection conn = config.build();
  PreparedStatement preparedStatement;
  ResultSet resultSet;
  Object obj;
  List<Object> list = new ArrayList<>();
  try {
   preparedStatement=conn.prepareStatement(mapping.getSql());
   if (mapping.getResultType() == null){
    throw new RuntimeException("返回的映射结果不能为空!");
   }
   resultSet = preparedStatement.executeQuery();
   int row = 0;
   ResultSetMetaData rd = resultSet.getMetaData();
   while (resultSet.next()){
    obj=resultToObject(resultSet,mapping.getResultType());
    row++;
    list.add(obj);
   }
   System.out.println("记录行数:"+row);
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return (T) list;
 }

 @Override
 public <T> T queryValue(Mapping mapping, List<Object> params) {
  Connection conn = config.build();
  PreparedStatement preparedStatement;
  ResultSet resultSet;
  Object obj;
  List<Object> list = new ArrayList<>();
  try {
   preparedStatement=conn.prepareStatement(mapping.getSql());
   for (int i=0; i<params.size(); i++) {
    preparedStatement.setString(i+1, params.get(i).toString());
   }
   if (mapping.getResultType() == null){
    throw new RuntimeException("返回的映射结果不能为空!");
   }
   resultSet = preparedStatement.executeQuery();
   int row = 0;
   ResultSetMetaData rd = resultSet.getMetaData();
   while (resultSet.next()){
    obj=resultToObject(resultSet,mapping.getResultType());
    row++;
    list.add(obj);
   }
   System.out.println("记录行数:"+row);
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return (T) list;
 }

 @Override
 public int deleteValue(Mapping mapping, List<Object> params) {
  Connection conn = config.build();
  int rows = 0;
  PreparedStatement preparedStatement=null;
  try {
   preparedStatement = conn.prepareStatement(mapping.getSql());
   for (int i=0; i<params.size(); i++) {
    preparedStatement.setString(i+1, params.get(i).toString());
   }
   rows = preparedStatement.executeUpdate();
   if (rows != 0) {
    System.out.println("删除成功,受影响行数:"+rows);
   } else {
    System.out.println("删除失败,数据库无相应数据...");
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return rows;
 }

 @Override
 public int updateValue(Mapping mapping, List<Object> params) {
  Connection conn = config.build();
  int rows = 0;
  PreparedStatement preparedStatement=null;
  try {
   preparedStatement = conn.prepareStatement(mapping.getSql());
   for (int i=0; i<params.size(); i++) {
    preparedStatement.setString(i+1, params.get(i).toString());
   }
   rows = preparedStatement.executeUpdate();
   if (rows != 0) {
    System.out.println("修改成功,受影响行数:"+rows);
   } else {
    System.out.println("修改失败,数据库无相应数据...");
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return rows;
 }

 @Override
 public int insertValue(Mapping mapping, List<Object> params) {
  Connection conn = config.build();
  int rows = 0;
  PreparedStatement preparedStatement=null;
  try {
   preparedStatement = conn.prepareStatement(mapping.getSql());
   for (int i=0; i<params.size(); i++) {
    preparedStatement.setString(i+1, params.get(i).toString());
   }
   try {
    rows = preparedStatement.executeUpdate();
    if (rows != 0) {
     System.out.println("插入成功,受影响行数:"+rows);
    } else {
     System.out.println("插入失败...");
    }
   } catch (SQLException throwables) {
    throw new RuntimeException("插入重复 \"Key\" 值数据");
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return rows;
 }

 private <T> T resultToObject(ResultSet rs, Object object) {
  Object obj=null;

  try {
   Class<?> cls = object.getClass();
  /*
   这里为什么要通过class再new一个对象?
   因为如果不new一个新的对象,每次返回的都是形参上的object,
   而这个object都是同一个,会导致list列表后面覆盖前面值。
   */
   obj=cls.newInstance();
   //获取结果集元数据(获取此 ResultSet 对象的列的编号、类型和属性。)
   ResultSetMetaData rd=rs.getMetaData();
   for (int i = 0; i < rd.getColumnCount(); i++) {
    //获取列名
    String columnName=rd.getColumnLabel(i+1);
    //组合方法名
    String methodName="set"+columnName.substring(0, 1).toUpperCase()+columnName.substring(1);
    //获取列类型
    int columnType=rd.getColumnType(i+1);
    Method method=null;
    switch(columnType) {
     case java.sql.Types.VARCHAR:
     case java.sql.Types.CHAR:
      method=cls.getMethod(methodName, String.class);
      method.invoke(obj, rs.getString(columnName));
      break;
     case java.sql.Types.INTEGER:
      method=cls.getMethod(methodName, Integer.class);
      method.invoke(obj, rs.getInt(columnName));
      break;
     default:
      break;
    }
   }
  } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException | SQLException e) {
   e.printStackTrace();
  }
  return (T) obj;
 }
}

四、打包测试

4.1 将其打成 Jar 包

4.2 创建一个Maven项目,因为需要导入对应的包

<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- xml解析 -->
<dependency>
 <groupId>org.dom4j</groupId>
 <artifactId>dom4j</artifactId>
 <version>2.1.3</version>
</dependency>

<!-- Mysql -->
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.49</version>
</dependency>
<!-- 自己写的Mybatis,首先要将其放入本地仓库 -->
<dependency>
 <groupId>top.kk233</groupId>
 <artifactId>SimpMybatis</artifactId>
 <version>1.0.0</version>
</dependency>

⚡Maven导入本地Jar包方法自行百度,这里就不赘述。

4.3 创建数据库

这里提供一个我测试的,你们可以自行创建其他的

CREATE DATABASE IF NOT EXISTS `test`;
USE `test`;
CREATE TABLE `user` (
	`id` INT ( 10 ) NOT NULL,
	`sex` VARCHAR ( 2 ) NOT NULL,
	`password` VARCHAR ( 255 ) DEFAULT NULL,
	`username` VARCHAR ( 255 ) DEFAULT NULL,
	PRIMARY KEY ( `id` )
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8;
INSERT INTO `test`.`user` ( `id`, `sex`, `password`, `username` )
VALUES
	( 1, '男', '12344', '五六' ),
	( 2, '女', '12643', '张三' ),
	( 3, '男', '1245453', '李四' );

4.4 创建实体类

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 16:17
 */
public class User {
 private Integer id;
 private String sex;
 private String password;
 private String username;
 // setter、getter略
}

4.5 创建 UserMapper 接口

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 16:17
 */
public interface UserMapper {
 List<User> getUsers();

 List<User> getUserBySexAndName(String sex, String username);

 int deleteUserById(Integer id);

 int updateUserByName(String username, String password);

 int insertUser(int id, String sex, String password, String username);
}

4.6 创建 UserMapper.xml 映射文件

<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="top.kk233.mapper.UserMapper">
 <select id="getUsers" resultType="top.kk233.pojo.User">
  SELECT * FROM user
 </select>
 <select id="getUserBySexAndName" resultType="top.kk233.pojo.User">
  select * from user where sex=? and username=?
 </select>

 <delete id="deleteUserById" resultType="top.kk233.pojo.User">
  delete from user where id=?
 </delete>

 <update id="updateUserByName" resultType="top.kk233.pojo.User">
  update user set password=? where username=?
 </update>

 <insert id="insertUser" resultType="top.kk233.pojo.User">
  insert into user values(?,?,?,?)
 </insert>
</mapper>

4.7 创建 mybatis-config.xml 数据库配置文件

<?xml version="1.0" encoding="UTF-8"?>
<database>
 <property name="driverClassName">com.mysql.jdbc.Driver</property>
 <property name="url">jdbc:mysql://localhost:3306/test?useSSL=false</property>
 <property name="username">root</property>
 <property name="password">124760</property>
</database>

4.8 创建启动类测试

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 16:24
 */
public class app {

 public static void main(String[] args) {

  MySqlSession sql = new MySqlSession();
  UserMapper mapper = sql.getMapper(UserMapper.class);
  List<User> users = mapper.getUsers();
  users.forEach(System.out::println);
  System.out.println("==========================");
  List<User> users1 = mapper.getUserBySexAndName("女", "张三");
  users1.forEach(System.out::println);
  System.out.println("==========================");
  mapper.deleteUserById(1);
  System.out.println("==========================");
  mapper.updateUserByName("五六", "女");
  System.out.println("==========================");
  mapper.insertUser(10, "男", "123123", "五七");

 }
}

4.9 测试结果

👌测试成功,这就是本人所手写的Mybatis,虽然比较简单,但还是学习到了很多东西。

💥项目放在 Gitee 上有需要自行下载,觉得可以还请点个Star

到此这篇关于Mybatis实现动态增删改查功能的示例代码的文章就介绍到这了,更多相关mybatis增删改查内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot + Mybatis增删改查实战记录

    简介 SpringBoot和Mybatis是啥请自行百度,作者这里也是花了几天时间入门了这个框架用来完成任务,并且也算符合要求的完成了任务,期间也各种百度但是没找到自己想要的那种简单易懂的教程,所以踩了很多坑,写这个博客的目的就是为了让大家少踩一点坑,开始. 创建一个SpringBoot项目https://start.spring.io/ 点开这个网站,创建一个Springboot项目,如下图,这里用的是2.1.5,学技术嘛,就是要学新的. 选择依赖,点击左下角的Dependencies Web

  • Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(二)

    在上篇文章给大家介绍了Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(一),接下来我们添加分页相关的依赖,时间紧张,直接上代码了,贴上我的pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=

  • Mybatis增删改查mapper文件写法详解

      1. 插入 <mapper namespace="需要实现接口的全类名"> <insert id="需要实现的接口里的方法名" parameterType="方法参数类型,如果是对象要写全类名"> INSERT sql命令(命令里通过#{}获取对象属性) <!--注意属性名区分大小写 --> </insert> <mapper> EG: <mapper namespace=&q

  • Oracle + mybatis实现对数据的简单增删改查实例代码

    什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架. MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索.MyBatis 可以使用简单的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 本文将详细介绍利用Oracle + mybatis实现对数据的简单增删改查的相关内容,下面话不多说了,来一起看看详细的介绍

  • MyBatis中SqlSession实现增删改查案例

    前言 开博客这是第一次写系列文章,从内心上讲是有点担心自己写不好,写不全,毕竟是作为java/mybatis学习的过程想把学习的路线和遇到的问题都总结下来,也让知识点在脑海里能形成一个体系. 开发环境 idea2016.mybatis3.SQLServer2012 pom.xml.mybatis.xml.log4j.properties 先贴上pom.xml是因为他直接和搭建开发环境和测试环境有关系,mybatis.xml则是连接数据库,log4j.properties在学习阶段配置上有助于我们

  • spring boot2结合mybatis增删改查的实现

    1. 场景描述 本节结合springboot2.springmvc.mybatis.swagger2等,搭建一个完整的增删改查项目,希望通过这个基础项目,能帮忙朋友快速上手springboot2项目. 2. 解决方案 2.1新建springboot项目 使用idea新建springboot项目(springboot项目快速搭建) (1)new project (2)gav设置 2.2 项目整体图及说明2.2.1 整体图 2.2.2 说明 项目包含4大内容 (1)pom.xml maven项目必备

  • SpringMVC4 + MyBatis3 + SQL Server 2014整合教程(含增删改查分页)

    前言 说起整合自然离不开ssm,我本身并不太喜欢ORM,尤其是MyBatis,把SQL语句写在xml里,尤其是大SQL,可读性不高,出错也不容易排查. 开发环境 idea2016.SpringMVC4.Mybatis3 项目结构 SSM整合 1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&qu

  • Mybatis 条件查询 批量增删改查功能

    模糊查询: @Select({ "SELECT * FROM account where account like CONCAT('%',#{query},'%') or email like CONCAT('%',#{query},'%')" }) Account findAccountByAccountOrMail(@Param("query") String query); 批量添加: @Insert({ "<script>"

  • Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(一)

    环境搭建 spring boot的简介 以往我们开发时用到spring总是避免不了繁琐的配置,例如我们要配置一个数据库连接,可能需要以下几步: 1.编写jdbc.properties配置文件: 2.创建spring的配置文件,加入spring配置文件前缀.配置数据库连接信息以及sqlsessionFactory等等: 3.还要在web.xml文件中加入spring的监听. springboot的出现大大简化了项目的搭建过程(spring配置以及maven配置),让我们专注于应用功能的开发,而不是

  • Mybatis实现动态增删改查功能的示例代码

    一.Mybatis 流程简介 最近在看 Mybatis 的源码,大致了解整个框架流程后便手写了一个特别简单的SimpMybatis的小Demo,来巩固这整个框架的学习.下图是我所画的框架大致执行流程:

  • Spring boot+mybatis+thymeleaf 实现登录注册增删改查功能的示例代码

    本文重在实现理解,过滤器,业务,逻辑需求,样式请无视.. 项目结构如下 1.idea新建Spring boot项目,在pom中加上thymeleaf和mybatis支持.pom.xml代码如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3

  • koa+mongoose实现简单增删改查接口的示例代码

    配合上一篇文章的联系人应用(https://www.jb51.net/article/161160.htm),实现配套的基于nodejs的后台增删改查接口 1. 所需工具 node.js mongoDB 2. 主要node模块 koa(https://koa.bootcss.com,一个nodejs的开发框架),mongoose(https://mongoosejs.com,mongDB操作工具) 3. 目录结构 4. 启动MongoDB 首先在MongoDB安装盘的根目录下(这里假设是D盘)新

  • C#对Access进行增删改查的完整示例

    这篇文章整理了C#对Access数据库的查询.添加记录.删除记录和更新数据等一系列的操作示例,有需要的可以参考学习. 首先是AccessHelper.cs,网上有下载,下面附送一份: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.OleDb; using System.Data

  • mybatis <foreach>标签动态增删改查方式

    目录 <foreach>标签动态增删改查 mybatis<foreach> 实战 有了建表以及插入,当然少不了删除和更新 mapper.xml中<foreach>标签使用 适用场景 <foreach>标签动态增删改查 mybatis<foreach> 有的时候在项目中需要查询某个列表时,可能会在代码中进行嵌套循环再取值,其实mybatis提供了这么一个标签,可以在SQL中进行循环(是不是很酸爽) 先来了解一下foreach这个标签有哪些元素: i

  • SpringBoot整合Mybatis与thymleft实现增删改查功能详解

    首先我们先创建项目 注意:创建SpringBoot项目时一定要联网不然会报错 项目创建好后我们首先对 application.yml 进行编译 #指定端口号server: port: 8888#配置mysql数据源spring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://localhost:3306/nba?serverTimezone=Asia/Shanghai    use

  • Mybatis开发环境搭建实现数据的增删改查功能

    config.xml的配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 拿到数据库

  • MyBatis存储过程、MyBatis分页、MyBatis一对多增删改查操作

    一.用到的实体类如下: Student.java package com.company.entity; import java.io.Serializable; import java.util.Date; public class Student implements Serializable{ private static final long serialVersionUID = 1L; private int id; private String name; private Date

  • BootstrapTable与KnockoutJS相结合实现增删改查功能【一】

    Bootstrap是一个前端框架,解放Web开发者的好东东,展现出的UI非常高端大气上档次,理论上可以不用写一行css.只要在标签中加上合适的属性即可. KnockoutJS是一个JavaScript实现的MVVM框架.非常棒.比如列表数据项增减后,不需要重新刷新整个控件片段或自己写JS增删节点,只要预先定义模板和符合其语法定义的属性即可.简单的说,我们只需要关注数据的存取. 一.Knockout.js简介 1.Knockout.js和MVVM 如今,各种前端框架应接不暇,令人眼花缭乱,有时不得

随机推荐