MyBatis学习笔记——2

MyBatis学习笔记——2

  • 一、MyBatis核心配置文件详解
    • 1.1、environment(环境)
    • 1.2、transactionManager(事务管理器)
    • 1.3、dataSource(数据源)
    • 1.4、properties
    • 1.5、mapper
  • 二、在WEB中应用MyBatis(使用MVC架构模式)
    • 2.1、需求描述
    • 2.2、数据库设计准备数据
    • 2.3、环境搭建
      • 2.3.1、前端页面index.html
      • 2.3.2、创建pojo包、service包、dao包、web包、utils包
      • 2.3.3、定义pojo类:Account
      • 2.3.4、编写AccountDao接口,以及AccountDaoImpl实现类
      • 2.3.5、AccountDaoImpl中编写了mybatis代码,需要编写SQL映射文件了
      • 2.3.6、编写AccountService接口以及AccountServiceImpl
      • 2.3.7、编写AccountController
    • 2.4、MyBatis对象作用域以及事务问题
      • 2.4.1、MyBatis核心对象的作用域
      • 2.4.1、事务问题
  • 三、javassist生成类
    • 3.1、Javassist的使用
    • 3.2、使用Javassist动态生成DaoImpl类
  • 四、MyBatis中接口代理机制及使用

一、MyBatis核心配置文件详解

1.1、environment(环境)

  • 一般一个数据库会对应一个SqlSessionFactory对象
  • 一个环境environment会对应一个SqlSessionFactory对象
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--默认使用开发环境--><!--<environments default="dev">--><!--默认使用生产环境--><environments default="production"><!--开发环境--><environment id="dev"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/powernode"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment><!--生产环境--><environment id="production"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="CarMapper.xml"/></mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="car"><insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})</insert>
</mapper>
package com.powernode.mybatis;import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;public class ConfigurationTest {@Testpublic void testEnvironment() throws Exception{// 准备数据Car car = new Car();car.setCarNum("133");car.setBrand("丰田霸道");car.setGuidePrice(50.3);car.setProduceTime("2020-01-10");car.setCarType("燃油车");// 一个数据库对应一个SqlSessionFactory对象// 两个数据库对应两个SqlSessionFactory对象,以此类推SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// 使用默认数据库SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession = sqlSessionFactory.openSession(true);int count = sqlSession.insert("insertCar", car);System.out.println("插入了几条记录:" + count);// 使用指定数据库SqlSessionFactory sqlSessionFactory1 = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "dev");SqlSession sqlSession1 = sqlSessionFactory1.openSession(true);int count1 = sqlSession1.insert("insertCar", car);System.out.println("插入了几条记录:" + count1);}
}

1.2、transactionManager(事务管理器)

  • 作用:配置事务管理器。指定mybatis具体使用什么方式去管理事务。
  • type属性有两个值:
    • 第一个:JDBC:使用原生JDBC代码来管理事务
      • conn.setAutoCommit(false);
      • conn.commit();
    • 第二个:MANAGED:mybatis不再负责事务的管理,将事务管理交给其他的JavaEE容器
      • spring
  • 不区分大小写,但是不能写其他值,只能是二选一:
    • jdbc、managed
  • 在mybatis中提供了一个事务管理器接口:Transaction
    • 该接口下有两个实现类:
      • jdbcTransaction
      • managedTransaction
    • 如果type="JDBC",那么底层会实例化JdbcTransaction对象。
    • 如果type="MANAGED",那么底层会实例化ManagedTransaction对象

当事务管理器是:JDBC

  • 采用JDBC的原生事务机制:
    • 开启事务:conn.setAutoCommit(false);
    • 处理业务…
    • 提交事务:conn.commit();

当事务管理器是:MANAGED

  • 交给容器去管理事务,但目前使用的是本地程序,没有容器的支持,当mybatis找不到容器的支持时:没有事务。也就是说只要执行一条DML语句,则提交一次。

1.3、dataSource(数据源)

dataSource配置:

  1. dataSource被称为数据源。
  2. dataSource作用是什么?
    • 为程序提供Connection对象。(但凡是给程序提供Connection对象的,都叫做数据源。)
  3. 数据源实际上是一套规范。JDK中有这套规范: javax.sql.DataSource(这个数据源的规范,这套接口实际上是JDK规定的。)
  4. 我们自己也可以编写数据源组件,只要实现javax.sql.DataSource接口就行了。实现接口当中所有的方法。这样就有了自己的数据源。
    比如你可以写一个属于自己的数据库连接池(数据库连接池是提供连接对象的,所以数据库连接池就是一个数据源)。
  5. 常见的数据源组件有哪些呢【常见的数据库连接池有哪些呢】?
    • 阿里巴巴的德鲁伊连接池:druid
    • c3p0
    • dbcp
  6. type属性 用来指定数据源的类型,就是指定具体使用什么方式来获取Connection对象:
    type属性 有三个值:必须是三选一。
    type=“[ UNPOOLED | POOLED | JNDI ]”
    • UNPOOLED:不使用数据库连接池技术。每一次请求过来之后,都是创建新的Connection对象
    • POOLED:使用mybatis自己实现的数据库连接池
    • JNDI:集成其它第三方的数据库连接池
  • JNDI是一套规范。谁实现了这套规范呢?大部分的web容器都实现了JNDI规范:
    例如: Tomcat、Jetty、WebLogic、WebSphere,这些服务器(容器)都实现了JNDI规范。
    JNDI是: java命名目录接口。Tomcat服务器实现了这个规范。

  • 不同配置下的属性不同,通过参考官方手册进行编辑配置

  • 提醒:正常使用连接池的话,池中有很多参数是需要设置的。设置好参数,可以让连接池发挥的更好。事半功倍的效果。

  • 具体连接池当中的参数如何配置呢?需要反复的根据当前业务情况进行测试。

属性作用
poolMaximumActiveConnections最大的活动的连接数量。默认值10
poolMaximumIdleConnections最大的空闲连接数量。默认值5
poolMaximumCheckoutTime强行回归池的时间。默认值20秒
poolTimeToWait当无法获取到空闲连接时,每隔20秒打印一次日志,避免因代码配置有误,导致傻等。(时长是可以配置的)

当然,还有其他属性。对于连接池来说,以上几个属性比较重要。
最大的活动的连接数量就是连接池连接数量的上限。默认值10,如果有10个请求正在使用这10个连接,第11个请求只能等待空闲连接。
最大的空闲连接数量。默认值5,如何已经有了5个空闲连接,当第6个连接要空闲下来的时候,连接池会选择关闭该连接对象。来减少数据库的开销。
需要根据系统的并发情况,来合理调整连接池最大连接数以及最多空闲数量。充分发挥数据库连接池的性能。【可以根据实际情况进行测试,然后调整一个合理的数量。】

1.4、properties

mybatis提供了更加灵活的配置,连接数据库的信息可以单独写到一个属性资源文件中,假设在类的根路径下创建jdbc.properties文件,配置如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/powernode

在mybatis核心配置文件中引入并使用:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--引入外部属性资源文件--><properties resource="jdbc.properties"><property name="jdbc.username" value="root"/><property name="jdbc.password" value="root"/></properties><environments default="dev"><environment id="dev"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--${key}使用--><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="CarMapper.xml"/></mappers>
</configuration>

properties两个属性:

  • resource:这个属性从类的根路径下开始加载。【常用的。】
  • url:从指定的url加载,假设文件放在d:/jdbc.properties,这个url可以写成:file:///d:/jdbc.properties。注意是三个斜杠哦。

注意:如果不知道mybatis-config.xml文件中标签的编写顺序的话,可以有两种方式知道它的顺序:

  • 第一种方式:查看dtd约束文件。
  • 第二种方式:通过idea的报错提示信息。【一般采用这种方式】

1.5、mapper

mapper标签用来指定SQL映射文件的路径,包含多种指定方式,这里先主要看其中两种:
第一种:resource,从类的根路径下开始加载【比url常用】

<mappers><mapper resource="CarMapper.xml"/>
</mappers>

如果是这样写的话,必须保证类的根下有CarMapper.xml文件。
如果类的根路径下有一个包叫做test,CarMapper.xml如果放在test包下的话,这个配置应该是这样写:

<mappers><mapper resource="test/CarMapper.xml"/>
</mappers>

第二种:url,从指定的url位置加载
假设CarMapper.xml文件放在d盘的根下,这个配置就需要这样写:

<mappers><mapper url="file:///d:/CarMapper.xml"/>
</mappers>

二、在WEB中应用MyBatis(使用MVC架构模式)

目标:

  • 掌握mybatis在web应用中怎么用
  • mybatis三大对象的作用域和生命周期
  • ThreadLocal原理及使用
  • 巩固MVC架构模式
  • 为学习MyBatis的接口代理机制做准备

实现功能:

  • 银行账户转账

使用技术:

  • HTML + Servlet + MyBatis

WEB应用的名称:

  • bank

2.1、需求描述

在这里插入图片描述

2.2、数据库设计准备数据

在这里插入图片描述
在这里插入图片描述

2.3、环境搭建

  • 配置tomcat
  • 在pop文件中引入依赖
  • 设计好前端页面
  • 导入资源配置文件

2.3.1、前端页面index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>银行账户转账</title>
</head>
<body>
<!--/bank是应用的根,部署web应用到tomcat的时候一定要注意这个名字-->
<form action="/bank/transfer" method="post">转出账户:<input type="text" name="fromActno"/><br>转入账户:<input type="text" name="toActno"/><br>转账金额:<input type="text" name="money"/><br><input type="submit" value="转账"/>
</form>
</body>
</html>

2.3.2、创建pojo包、service包、dao包、web包、utils包

  • com.powernode.bank.pojo
  • com.powernode.bank.service
  • com.powernode.bank.service.impl
  • com.powernode.bank.dao
  • com.powernode.bank.dao.impl
  • com.powernode.bank.web.controller
  • com.powernode.bank.exception
  • com.powernode.bank.utils将之前编写的SqlSessionUtil工具类拷贝到该包下。

2.3.3、定义pojo类:Account

package com.powernode.bank.pojo;/*** 银行账户类* @author 老杜* @version 1.0* @since 1.0*/
public class Account {private Long id;private String actno;private Double balance;@Overridepublic String toString() {return "Account{" +"id=" + id +", actno='" + actno + '\'' +", balance=" + balance +'}';}public Account() {}public Account(Long id, String actno, Double balance) {this.id = id;this.actno = actno;this.balance = balance;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getActno() {return actno;}public void setActno(String actno) {this.actno = actno;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}
}

2.3.4、编写AccountDao接口,以及AccountDaoImpl实现类

分析dao中至少要提供几个方法,才能完成转账:

  • 转账前需要查询余额是否充足:selectByActno
  • 转账时要更新账户:update

AccountDao

package com.powernode.bank.dao;import com.powernode.bank.pojo.Account;/*** 账户数据访问对象* @author 老杜* @version 1.0* @since 1.0*/
public interface AccountDao {/*** 根据账号获取账户信息* @param actno 账号* @return 账户信息*/Account selectByActno(String actno);/*** 更新账户信息* @param act 账户信息* @return 1表示更新成功,其他值表示失败*/int update(Account act);
}

AccountDaoImpl

package com.powernode.bank.dao.impl;import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;public class AccountDaoImpl implements AccountDao {@Overridepublic Account selectByActno(String actno) {SqlSession sqlSession = SqlSessionUtil.openSession();Account act = (Account)sqlSession.selectOne("selectByActno", actno);sqlSession.close();return act;}@Overridepublic int update(Account act) {SqlSession sqlSession = SqlSessionUtil.openSession();int count = sqlSession.update("update", act);sqlSession.commit();sqlSession.close();return count;}
}

2.3.5、AccountDaoImpl中编写了mybatis代码,需要编写SQL映射文件了

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="account"><select id="selectByActno" resultType="com.powernode.bank.pojo.Account">select * from t_act where actno = #{actno}</select><update id="update">update t_act set balance = #{balance} where actno = #{actno}</update>
</mapper>

2.3.6、编写AccountService接口以及AccountServiceImpl

MoneyNotEnoughException

package com.powernode.bank.exception;/*** 余额不足异常* @author 老杜* @version 1.0* @since 1.0*/
public class MoneyNotEnoughException extends Exception{public MoneyNotEnoughException(){}public MoneyNotEnoughException(String msg){ super(msg); }
}

AppException

package com.powernode.bank.exception;/*** 应用异常* @author 老杜* @version 1.0* @since 1.0*/
public class AppException extends Exception{public AppException(){}public AppException(String msg){ super(msg); }
}

AccountService

package com.powernode.bank.service;import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;/*** 账户业务类。* @author 老杜* @version 1.0* @since 1.0*/
public interface AccountService {/*** 银行账户转正* @param fromActno 转出账户* @param toActno 转入账户* @param money 转账金额* @throws MoneyNotEnoughException 余额不足异常* @throws AppException App发生异常*/void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException;
}

AccountServiceImpl

package com.powernode.bank.service.impl;import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.dao.impl.AccountDaoImpl;
import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.service.AccountService;public class AccountServiceImpl implements AccountService {private AccountDao accountDao = new AccountDaoImpl();@Overridepublic void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException {// 查询转出账户的余额Account fromAct = accountDao.selectByActno(fromActno);if (fromAct.getBalance() < money) {throw new MoneyNotEnoughException("对不起,您的余额不足。");}try {// 程序如果执行到这里说明余额充足// 修改账户余额Account toAct = accountDao.selectByActno(toActno);fromAct.setBalance(fromAct.getBalance() - money);toAct.setBalance(toAct.getBalance() + money);// 更新数据库accountDao.update(fromAct);accountDao.update(toAct);} catch (Exception e) {throw new AppException("转账失败,未知原因!");}}
}

2.3.7、编写AccountController

package com.powernode.bank.web.controller;import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;
import com.powernode.bank.service.AccountService;
import com.powernode.bank.service.impl.AccountServiceImpl;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 账户控制器* @author 老杜* @version 1.0* @since 1.0*/
@WebServlet("/transfer")
public class AccountController extends HttpServlet {private AccountService accountService = new AccountServiceImpl();@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取响应流response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();// 获取账户信息String fromActno = request.getParameter("fromActno");String toActno = request.getParameter("toActno");double money = Integer.parseInt(request.getParameter("money"));// 调用业务方法完成转账try {accountService.transfer(fromActno, toActno, money);out.print("<h1>转账成功!!!</h1>");} catch (MoneyNotEnoughException e) {out.print(e.getMessage());} catch (AppException e) {out.print(e.getMessage());}}
}

2.4、MyBatis对象作用域以及事务问题

2.4.1、MyBatis核心对象的作用域

  • SqlSessionFactoryBuilder

    • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
  • SqlSessionFactory

    • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
  • SqlSession

    • 每个线程都应该有它自己的 SqlSession 实例SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
    try (SqlSession session = sqlSessionFactory.openSession()) {// 你的应用逻辑代码
    }
    

2.4.1、事务问题

为了保证service和dao中使用的SqlSession对象是同一个,可以将SqlSession对象存放到ThreadLocal当中。修改SqlSessionUtil工具类:

package com.powernode.bank.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class SqlSessionUtil {private static SqlSessionFactory sqlSessionFactory;/*** 类加载时初始化sqlSessionFactory对象*/static {try {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));} catch (Exception e) {e.printStackTrace();}}private static ThreadLocal<SqlSession> local = new ThreadLocal<>();/*** 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。** @return 新的会话对象*/public static SqlSession openSession() {SqlSession sqlSession = local.get();if (sqlSession == null) {sqlSession = sqlSessionFactory.openSession();local.set(sqlSession);}return sqlSession;}/*** 关闭SqlSession对象* @param sqlSession*/public static void close(SqlSession sqlSession){if (sqlSession != null) {sqlSession.close();}local.remove();}
}

修改dao中的方法:AccountDaoImpl中所有方法中的提交commit和关闭close代码全部删除。

三、javassist生成类

3.1、Javassist的使用

我们要使用javassist,首先要引入它的依赖

<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.29.1-GA</version>
</dependency>

样例代码:

package com.powernode.javassist;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;import java.lang.reflect.Method;public class JavassistTest {public static void main(String[] args) throws Exception {// 获取类池ClassPool pool = ClassPool.getDefault();// 创建类CtClass ctClass = pool.makeClass("com.powernode.javassist.Test");// 创建方法// 1.返回值类型 2.方法名 3.形式参数列表 4.所属类CtMethod ctMethod = new CtMethod(CtClass.voidType, "execute", new CtClass[]{}, ctClass);// 设置方法的修饰符列表ctMethod.setModifiers(Modifier.PUBLIC);// 设置方法体ctMethod.setBody("{System.out.println(\"hello world\");}");// 给类添加方法ctClass.addMethod(ctMethod);// 调用方法Class<?> aClass = ctClass.toClass();Object o = aClass.newInstance();Method method = aClass.getDeclaredMethod("execute");method.invoke(o);}
}

运行要注意:加两个参数,要不然会有异常。

  • --add-opens java.base/java.lang=ALL-UNNAMED
  • --add-opens java.base/sun.net.util=ALL-UNNAMED

3.2、使用Javassist动态生成DaoImpl类

package com.Smulll.javassist;import com.Smulll.bank.dao.AccountDao;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.junit.Test;import java.lang.reflect.Method;
import java.util.Arrays;public class test1{@Testpublic void testGenerateInterfaceAll() throws Exception {//制造类池ClassPool pool = ClassPool.getDefault();//制造类CtClass ctClass = pool.makeClass("com.Smulll.bank.dao.impl.AccountDaoImpl");//制造接口CtClass ctInterface = pool.makeClass("com/Smulll/bank/dao/AccountDao");//使类实现接口ctClass.addInterface(ctInterface);//实现接口中的方法//获取接口中所有的方法Method[] methods = AccountDao.class.getDeclaredMethods();Arrays.stream(methods).forEach(method -> {// method是接口中的抽象方法// 把method抽象方法给实现了try {// public void delete(){System.out.println(111);}StringBuilder methodCode = new StringBuilder();methodCode.append("public ");//追加修饰符列表methodCode.append(method.getReturnType().getName());//追加返回值类型methodCode.append(" ");methodCode.append(method.getName());methodCode.append("(");//添加参数Class<?>[] parameterTypes = method.getParameterTypes();for (int i = 0; i < parameterTypes.length; i++) {Class<?> parameter =  parameterTypes[i];methodCode.append(parameter.getName());methodCode.append(" ");methodCode.append("arg"+i);if (i != parameterTypes.length-1){methodCode.append(",");}}methodCode.append("){System.out.println(11111);");//添加返回值String returnName = method.getReturnType().getSimpleName();//获取返回值类名的简类名if ("int".equals(returnName)){methodCode.append("return 1;");} else if ("String".equals(returnName)) {methodCode.append("return \"hello\";");}methodCode.append("}");CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);//将方法都加到类中ctClass.addMethod(ctMethod);} catch (CannotCompileException e) {e.printStackTrace();}});//在内存中生成类,同时生成的类加载到JVM当中Class<?> aClass = ctClass.toClass();AccountDao accountDao = (AccountDao)aClass.newInstance();//执行里面的方法accountDao.delete();accountDao.insert("acton");accountDao.update("acton",100.00);accountDao.selectByActon("acton");}
}

修改AccountMapper.xml文件:namespace必须是dao接口的全限定名称,id必须是dao接口中的方法名:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.powernode.bank.dao.AccountDao"><select id="selectByActno" resultType="com.powernode.bank.pojo.Account">select * from t_act where actno = #{actno}</select><update id="update">update t_act set balance = #{balance} where actno = #{actno}</update>
</mapper>

四、MyBatis中接口代理机制及使用

好消息!!!其实以上所讲内容mybatis内部已经实现了。直接调用以下代码即可获取dao接口的代理类:

AccountDao accountDao = (AccountDao)sqlSession.getMapper(AccountDao.class);

使用以上代码的前提是:AccountMapper.xml文件中的namespace必须和dao接口的全限定名称一致,id必须和dao接口中方法名一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

轮播图添加删除

轮播图页面和对话框搭建 页面简单布局 <template><div id"banner"><el-space direction"vertical" :size"20" style"width: 100%"><h1>轮播图管理</h1><div style"text-align: right"&g…

商城-学习整理-基础-分布式组件(三)

目录 一、前言二、Spring Cloud&Spring Cloud Alibaba1、Spring Cloud 与Spring Cloud Alibaba简介2、为什么使用Spring Cloud Alibaba3、版本选择4、项目中的依赖 三、Spring Cloud Alibaba-Nacos作为注册中心1、Nacos1&#xff09;、下载 nacos-server2&#xff09;、启动…

42. 接雨水

42.接雨水 这是一个简单的动态规划问题&#xff0c;虽然leetcode将它归结为困难。 但是我感觉它难度应该达不到&#xff0c;可能归结为中等比较合适0x1 题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨…

python flask 返回中文乱码

使用flask返回数据中带有中文的时候会显示成乱码(ascii)&#xff0c; 中文报文&#xff1a; ABAP中的三大财务报表是&#xff1a;* **资产负债表** * **收入证明** * **现金流量表**这些报表全面概述了公司的财务状况和业绩。* **资产负债表**显示公司在特定时间点的资产、负…

【Python数据分析】Python基础知识篇

&#x1f389;欢迎来到Python专栏~Python基础知识篇 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大…

LeetCode[1508]子数组和排序后的区间和

难度&#xff1a;Medium 题目&#xff1a; 给你一个数组 nums &#xff0c;它包含 n 个正整数。你需要计算所有非空连续子数组的和&#xff0c;并将它们按升序排序&#xff0c;得到一个新的包含 n * (n 1) / 2 个数字的数组。 请你返回在新数组中下标为 left 到 right &#…

将请求参数数据推送至RabbitMQ队列中并且捕捉消息没有到达交换机的异常

1&#xff1a;自定义mq信息类&#xff08;我的交换这些信息都从nacos上直接取的&#xff0c;怎么从nacos取配置信息看上篇文章&#xff09;&#xff1a; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;impo…

GB2312编码

说明 GB2312代码表用两个字节表示一个图形字符&#xff0c;两个字节中前面的字节为第一字节&#xff0c;后面的字节为第二字节。 区位码&#xff1a; GB2312代码表分成94个区&#xff0c;范围为1-94&#xff0c;区的编号由第一字节表示&#xff1b;每个区有94位&#xff0c;范…

AE 3D粒子插件trapcode particular 新版本

Trapcode Particular for Mac是目前AE系列的插件中最火爆最流行的一款三维粒子插件&#xff0c;是属于Red Giant Trapcode Suite&#xff08;红巨人粒子特效套装插件&#xff09;中的一款粒子插件。该软件提供了多达一百余种粒子效果供用户使用&#xff0c;可以产生各种各样的自…

【mac系统】mac系统调整妙控鼠标速度

当下环境&#xff1a; mac系统版本&#xff0c;其他系统应该也可以&#xff0c;大家可以自行试下&#xff1a; 鼠标 mac妙控鼠标&#xff0c;型号A1657 问题描述&#xff1a; 通过mac系统自带的鼠标速度调节按钮&#xff0c;调到最大后还是感觉移动速度哦过慢 问题解决&…

【Docker】什么是Docker呢?本文带你洞悉

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;目前专攻C/C、Python、Java等方向&#xff0c;一个正在慢慢前行的普通人。 &#x1f3c0;系列专栏&#xff1a;陈童学的日记 &#x1f4a1;其他专栏&#xff1a;CSTL、蓝桥杯&am…

学习day49

computed和watch的区别 1.computed能完成的功能&#xff0c;watch都可以实现 2.watch能完成的&#xff0c;computed不一定能实现&#xff0c;例如&#xff1a;watch可以进行异步操作 两个重要的小原则 1.所被Vue管理的函数&#xff0c;最好写成普通函数&#xff0c;这样this的指…

90道渗透测试面试题(附答案)

2023年已经快过去一半了&#xff0c;不知道小伙伴们有没有找到自己心仪的工作呀。最近后台收到不少小伙伴说要我整理一些渗透测试的面试题&#xff0c;今天它来了&#xff01;觉得对你有帮助的话记得点个赞再走哦~ 1、什么是渗透测试&#xff1f; 渗透测试是一种评估计算机系统…

【MATLAB】 二维绘图,三维绘图的方法与函数

目录 MATLAB的4种二维图 1.线图 2.条形图 3.极坐标图 4.散点图 三维图和子图 1.三维曲面图 2.子图 MATLAB的4种二维图 1.线图 plot函数用来创建x和y值的简单线图 x 0:0.05:30; %从0到30&#xff0c;每隔0.05取一次值 y sin(x); plot(x,y) %若(x,y,LineWidth,2) 可…

【ShaderToy中图形效果转译到UnityShaderlab案例分享,实现粒子场_ParticleField】

Shader"ShaderToy/ParticleField" {Properties{_iMouse("iMouse", Vector) = (0,0,0,0)}SubSha

解密动态内存管理的奥秘(含内存4个函数)

目录 一.为什么存在动态内存管理 二.动态内存函数的介绍 1. malloc函数&#xff08;memory alloc 内存开辟&#xff09; 函数介绍&#xff1a; malloc函数使用举例代码&#xff1a; 2.free&#xff08;释放&#xff09; 函数介绍&#xff1a; 代码的示例&#xff1a…

C#WinForm获取当前活动子窗体使用鼠标滚轮事件改变窗体大小

获取当前活动子窗体使用鼠标滚轮事件改变窗体大小&#xff0c;实例在文末&#xff0c;可下载。 这个主要分三个重点 第一步 我们需要让子窗体显示在父窗体中 Form22 new Form2(); Form22.TopLevel false; // 不是顶级窗体 //Form22.Parent this;// 设置父窗体 一定不要…

配置NFS服务

环境 环境 ubuntu 10.4 vm 7.1 终端 ifconfig 得到 ubuntu资料 INET ADDR 192.168.0.4 BCAST 192.168.0.255 MASK 255.255.255.0 操作前先关闭防火墙 关闭防火墙&#xff1a; 命令&#xff1a;sudo ufw disable 打开防火墙 命令&#xff1a;sudo ufw enable 配置过程 一 安…

机器人SLAM导航学习-All in one

参考引用 张虎&#xff0c;机器人SLAM导航核心技术与实战[M]. 机械工业出版社&#xff0c;2022.本博客未详尽之处可自行查阅上述书籍 一、编程基础篇 1. ROS 入门必备知识 ROS学习笔记&#xff08;文章链接汇总&#xff09; 2. C 编程范式 《21天学通C》读书笔记&#xff0…

RabbitMQ

文章目录 RabbitMQ初识MQ同步和异步通讯同步通讯异步通讯 技术对比 RabbitMq安装RabbitMQ架构RabbitMQ消息模型publisher实现consumer实现总结 SpringAMQPBasic Queue 简单队列模型WorkQueue发布/订阅FanoutDirectTopic 消息转换器 RabbitMQ 初识MQ 同步和异步通讯 微服务间…