溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

發(fā)布時間:2021-04-02 09:34:42 來源:億速云 閱讀:349 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Mybatis怎么實現(xiàn)動態(tài)增刪改查功能的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

一、Mybatis 流程簡介

最近在看 Mybatis 的源碼,大致了解整個框架流程后便手寫了一個特別簡單的SimpMybatis的小Demo,來鞏固這整個框架的學(xué)習。下圖是我所畫的框架大致執(zhí)行流程:

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

對上圖分析后得出結(jié)論:

1.Mybatis 的配置文件分為兩種,且這兩個配置文件會被封裝到 Configuration 中

  • 主配置文件(MybatisConfig.xml):配置 jdbc 等環(huán)境信息,全局唯一;

  • 映射文件(xxxMapper.xml):配置多個 Sql ,可有多個。

2.通過 Mybatis 配置文件得到 SqlSessionFactory ;
3.通過 SqlSessionFactory 得到 SqlSession,它就相當于 Request 請求;
4.SqlSession 調(diào)用底層的 Executor 執(zhí)行器來操作數(shù)據(jù)庫,同時執(zhí)行器有兩類實現(xiàn)

  • 基本實現(xiàn)

  • 帶有緩存功能的實現(xiàn)

5.解析傳入的參數(shù),對其進行封裝,執(zhí)行并返回結(jié)果;
以上就是我梳理的 Mybatis 大致流程,看似簡單,卻很精妙。

二、手寫簡化版 Mybatis 設(shè)計思路

2.1 簡化后的思路

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

2.2 讀取 XML 文件,建立連接

從圖中可以看出,MyConfig 負責與人交互。待讀取xml后,將屬性和連接數(shù)據(jù)庫的操作封裝在 MyConfig 對象中供后面的組件調(diào)用。本項目將使用 dom4j 來讀取xml文件,它具有性能優(yōu)異和非常方便使用的特點。

2.3 創(chuàng)建SqlSession,搭建 Configuration 和 Executor 之間的橋梁

從流程圖中的箭頭可以看出,MySqlSession 的成員變量中必須得有 MyExecutorImpl 和 MyConfig 去集中做調(diào)配。一個Session僅擁有一個對應(yīng)的數(shù)據(jù)庫連接。類似于一個前段請求Request,它負責直接調(diào)用對應(yīng) execute(sql) 來做 CRUD 操作。

2.4 創(chuàng)建 MyExecutor,封裝 JDBC 操作數(shù)據(jù)庫

MyExecutor 是一個執(zhí)行器,負責SQL語句的生成和查詢緩存的維護,也就是 Jdbc 的代碼將在這里完成,不過本文只實現(xiàn)了單表,查詢緩存并未實現(xiàn)。

2.5 創(chuàng)建 MySqlSessionProxy,使用動態(tài)代理生成 Mapper 對象

只是希望對指定的接口生成一個對象,使得執(zhí)行它的時候能運行一句 sql,而接口無法直接調(diào)用方法,所以這里使用動態(tài)代理生成對象,在執(zhí)行時還是回到 MySqlSession 中調(diào)用查詢,最終由 MyExecutorImpl 做 JDBC查詢。這樣設(shè)計是為了單一職責,可擴展性更強。

三、實現(xiàn)自己的Mybatis

這次會將其打成 Jar 包,并將其導(dǎo)入項目實現(xiàn),做一個 Mybatis 的還原。

工程文件及目錄:

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

3.1 導(dǎo)入兩個所需 Jar 包:數(shù)據(jù)庫連接和XML解析

Maven 導(dǎo)入如下:

<!-- 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 創(chuàng)建 MyConfig 類,對兩大 XML 配置文件進行解析,并建立連接

/**
 * @author Kenelm
 * @version 1.0
 * @date 2020/11/22 12:17
 */
public class MyConfig {
 /**
  * 啟動應(yīng)用程序類加載器
  */
 private static final ClassLoader loader = ClassLoader.getSystemClassLoader();
 /**
  * 數(shù)據(jù)庫建立連接
  * @return 返回數(shù)據(jù)庫連接對象
  *
  */
 public Connection build() {

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

  // 獲取文件根節(jié)點
  Element root = parseXML(resource);
  // 獲取文件對應(yīng)的信息
  Map<String, String> jdbcMap = parseNodes(root);
  try {
   Class.forName(jdbcMap.get("driverClassName"));
  } catch (ClassNotFoundException e) {
   throw new RuntimeException("驅(qū)動器未找到,請重新檢查!");
  }
  Connection connect = null;
  try {
   connect = DriverManager.getConnection(jdbcMap.get("url"), jdbcMap.get("username"), jdbcMap.get("password"));
  } catch (SQLException throwables) {
   throw new RuntimeException("數(shù)據(jù)庫連接錯誤,請檢查路徑、用戶名、密碼是否輸入正確!");
  }
  return connect;
 }
 /**
  * 解析數(shù)據(jù)庫配置文件
  * @param resource 數(shù)據(jù)庫配置文件路徑
  * @return 獲取到的文件根節(jié)點
  */
 public static Element parseXML(String resource) {
  try {
   // 返回用于讀取指定資源的輸入流
   InputStream stream = loader.getResourceAsStream(resource);
   // 使用dom4j解析XML
   SAXReader reader = new SAXReader();
   // 使用SAX從給定流中讀取文件
   Document doc = reader.read(stream);
   // 獲取文件的根節(jié)點
   return doc.getRootElement();
  } catch (DocumentException e) {
   throw new RuntimeException("解析 XML 時發(fā)生錯誤!" + resource);
  }
 }
 /**
  * 解析主xml文件標簽節(jié)點
  * @param node 配置文件根節(jié)點
  * @return 返回從配置文件中拿到的開啟數(shù)據(jù)庫對應(yīng)值
  */
 private Map<String, String> parseNodes(Element node) {
  // 判斷根標簽名稱
  if (!node.getName().equals("database")) {
   throw new RuntimeException("數(shù)據(jù)庫配置文件根標簽名稱必須為【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的屬性內(nèi)容
  for (Element item : node.elements()) {
   // 獲取標簽中存放的值,并刪除其前導(dǎo)和結(jié)尾的空格
   String value = getValue(item);
   // 獲取標簽中 name 的名稱
   String name = item.attributeValue("name");
   // 如果name或value為空則有對應(yīng)值未輸入
   if (name == null || "".equals(value)) {
    throw new RuntimeException("[database]: <property> 中應(yīng)該包含名稱和值");
   }
   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 配置文件根節(jié)點
  * @return 如果有value值,則讀取;沒有設(shè)置value,則讀取內(nèi)容
  */
 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節(jié)點的nameSpace值存為接口名
   bean.setInterfaceName(root.attributeValue("nameSpace").trim());
   // 用來存儲方法的List
   List<Mapping> list = new ArrayList<Mapping>();
   //遍歷根節(jié)點下所有子節(jié)點
   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 是否有返回值都應(yīng)包括:resultType(個人偷懶,沒做判斷);... ...

3.3 MySqlSession 代理

MySqlSession 肯定不會自己去執(zhí)行,因為不能寫死所以使用動態(tài)代理來使代理類去實現(xiàn)具體方法。

/**
 * @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){
  //動態(tài)代理調(diào)用
  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("執(zhí)行查詢方法:" + mapping.getSql());
      if (args!=null) {
       System.out.println("參數(shù):"+ Arrays.toString(args));
       return sqlSession.selectValue(mapping, Arrays.asList(args));
      } else {
       System.out.println("參數(shù):null");
       return sqlSession.selectNull(mapping);
      }
     }
     // 判斷是否為刪除語句
     if ("delete".equals(mapping.getSqlType().toLowerCase())){
      System.out.println("執(zhí)行查詢方法:"+mapping.getSql());
      System.out.println("參數(shù):"+ Arrays.toString(args));
      return sqlSession.deleteValue(mapping, Arrays.asList(args));
     }
     // 判斷是否為更新語句
     if ("update".equals(mapping.getSqlType().toLowerCase())) {
      System.out.println("執(zhí)行查詢方法:"+mapping.getSql());
      System.out.println("參數(shù):"+ Arrays.toString(args));
      return sqlSession.updateValue(mapping, Arrays.asList(args));
     }
     // 判斷是否為插入語句
     if ("insert".equals(mapping.getSqlType().toLowerCase())) {
      System.out.println("執(zhí)行查詢方法:" + mapping.getSql());
      System.out.println("參數(shù):" + Arrays.toString(args));
      return sqlSession.insertValue(mapping, Arrays.asList(args));
     }
    }
   }
  }
  return null;
 }
}

?注意:通過上段代碼可知,映射文件必須和接口名稱保持一致。

3.4 創(chuàng)建對應(yīng)實體類和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 創(chuàng)建 MyExcutor 接口以及實現(xiàn)類

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 實現(xiàn)類

這里通過反射將結(jié)果轉(zhuǎn)換成對象

/**
 * @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("返回的映射結(jié)果不能為空!");
   }
   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("記錄行數(shù):"+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("返回的映射結(jié)果不能為空!");
   }
   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("記錄行數(shù):"+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("刪除成功,受影響行數(shù):"+rows);
   } else {
    System.out.println("刪除失敗,數(shù)據(jù)庫無相應(yīng)數(shù)據(jù)...");
   }
  } 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("修改成功,受影響行數(shù):"+rows);
   } else {
    System.out.println("修改失敗,數(shù)據(jù)庫無相應(yīng)數(shù)據(jù)...");
   }
  } 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("插入成功,受影響行數(shù):"+rows);
    } else {
     System.out.println("插入失敗...");
    }
   } catch (SQLException throwables) {
    throw new RuntimeException("插入重復(fù) \"Key\" 值數(shù)據(jù)");
   }
  } 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都是同一個,會導(dǎo)致list列表后面覆蓋前面值。
   */
   obj=cls.newInstance();
   //獲取結(jié)果集元數(shù)據(jù)(獲取此 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 包

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

4.2 創(chuàng)建一個Maven項目,因為需要導(dǎo)入對應(yīng)的包

<!-- 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導(dǎo)入本地Jar包方法自行百度,這里就不贅述。

4.3 創(chuàng)建數(shù)據(jù)庫

這里提供一個我測試的,你們可以自行創(chuàng)建其他的

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 創(chuàng)建實體類

/**
 * @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 創(chuàng)建 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 創(chuàng)建 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 創(chuàng)建 mybatis-config.xml 數(shù)據(jù)庫配置文件

<?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 創(chuàng)建啟動類測試

/**
 * @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 測試結(jié)果

Mybatis怎么實現(xiàn)動態(tài)增刪改查功能

測試成功,這就是本人所手寫的Mybatis,雖然比較簡單,但還是學(xué)習到了很多東西。

項目放在 Gitee 上有需要自行下載,覺得可以還請點個Star

感謝各位的閱讀!關(guān)于“Mybatis怎么實現(xiàn)動態(tài)增刪改查功能”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI