MyBatis 三大核心对象的作用域
SqlSessionFactoryBuilder
- 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
- SqlSessionFactoryBuilder 对象的作用就是创建 SqlSessionFactory 对象,只要有了 SqlSessionFactory 对象就不在需要 SqlSessionFactoryBuilder 对象,其就可以被垃圾回收器回收了
- 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
static { try { // 获取默认数据库环境对应的SqlSessionFactory对象 sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } catch (IOException e) { e.printStackTrace(); } }
- 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactory
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
- 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。
- 因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
// 默认数据库环境对应的SqlSessionFactory private static SqlSessionFactory sqlSessionFactory = null; static { try { // 获取默认数据库环境对应的SqlSessionFactory对象 sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } catch (IOException e) { e.printStackTrace(); } }
SqlSession
- 每个线程都应该有它自己的 SqlSession 实例。
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。
- 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。
- 下面的示例就是一个确保 SqlSession 关闭的标准模式:
try (SqlSession session = sqlSessionFactory.openSession()) { // 你的应用逻辑代码 }
使用 javassist 生成类
依赖
<dependencies> <!-- javassist --> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.1-GA</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
运行参数配置
- 出现下列报错,需要进行运行参数的配置,JDK高版本的问题,低版本没有java.base这个模块,但是高版本添加了这个模块
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @28c97a5
- –add-opens java.base/java.lang=ALL-UNNAMED
- –add-opens java.base/sun.net.util=ALL-UNNAMED
Javassist的使用
import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import java.lang.reflect.Method; /** * ClassName: Test * Package: PACKAGE_NAME * Description: * * @Author tcw * @Create 2023-05-31 15:54 * @Version 1.0 */ public class Test { @org.junit.Test public void tset01() throws Exception { // 获取类池,用于生成class ClassPool pool = ClassPool.getDefault(); // 使用类池制造类 // 方法参数为类的全类名 CtClass ctClass = pool.makeClass("cw.mybatis.bank.dao.impl.AccountDaoImpl"); // 类中方法的代码 String methodCode = "public void insert() { System.out.println(\"数据库正在新增信息...\");}"; // 制造类中的方法 // 参数一:类中方法的代码;参数二:为哪个类创建方法 CtMethod ctMethod = CtMethod.make(methodCode, ctClass); // 将创建的方法添加到类中 ctClass.addMethod(ctMethod); // 在内存中动态生成class,将类加载到JVM中 // 得到类对应的Class对象 // Class<?> aClass = ctClass.toClass(); ctClass.toClass(); // 加载类到JVM中 Class<?> aClass = Class.forName("cw.mybatis.bank.dao.impl.AccountDaoImpl"); // 利用动态生成的类进行对象的创建(使用无参构造方法) Object o = aClass.getDeclaredConstructor().newInstance(); // 获取类中的方法 Method insertMethod = aClass.getDeclaredMethod("insert"); // 调用新创建的对象的insert方法 insertMethod.invoke(o); } }
使用 javassist 动态生成类并实现接口
public interface AccountDao { void delete(); }
@org.junit.Test public void testGenerateImpl() throws Exception { // 获取类型用于类的制造 ClassPool pool = ClassPool.getDefault(); // 制造类 CtClass AccountDaoImpl = pool.makeClass("cw.study.mybatis.dao.impl.AccountDaoImpl"); // 制造接口 CtClass AccountDao = pool.makeInterface("cw.study.mybatis.dao.AccountDao"); // 添加接口到类中 AccountDaoImpl.addInterface(AccountDao); // 实现接口中的方法 // 方法的代码 String methodCode = "public void delete() {System.out.println(\"数据库正在删除信息...\");}"; // 制造AccountDaoImpl类的方法 CtMethod method = CtMethod.make(methodCode, AccountDaoImpl); // 将方法添加到类中 AccountDaoImpl.addMethod(method); // 在内存中生成类,并将类加载到JVM中 Class<?> AccountDaoImplClass = AccountDaoImpl.toClass(); // 创建对象 AccountDao accountDao = (AccountDao) AccountDaoImplClass.getDeclaredConstructor().newInstance(); // 调用方法 accountDao.delete(); }
使用 javassist 动态生成类并实现接口中所有方法
public interface AccountDao { void delete(); int insert(String actno); int update(String actno, Double balance); String selectByActno(String actno); }
@org.junit.Test public void testGenerateAccountDaoImpl() throws Exception { // 获取类池 ClassPool pool = ClassPool.getDefault(); // 制造类 CtClass ctClass = pool.makeClass("cw.study.mybatis.dao.impl.AccountDaoImpl"); // 制造接口 CtClass ctInterface = pool.makeInterface("cw.study.mybatis.dao.AccountDao"); // 类实现接口 ctClass.addInterface(ctInterface); // 获取接口中的所有方法 Method[] methods = AccountDao.class.getDeclaredMethods(); // 遍历接口中的每个方法实现接口方法 Arrays.stream(methods).forEach(method -> { // 实现接口方法 // public void update(String actno, Double balance) {} StringBuilder builder = new StringBuilder(); // 添加访问权限修饰符 builder.append("public "); // 添加返回值类型 builder.append(method.getReturnType().getName()); builder.append(" "); // 追加方法名 builder.append(method.getName()); builder.append("("); // 获取方法的形参列表 Parameter[] parameters = method.getParameters(); // 遍历追加形参列表 for (int i = 0; i < parameters.length; i++) { // 追加形参列表中形参的类型 builder.append(parameters[i].getType().getName()); builder.append(" "); // 追加形参名 parameters[i].getName() 获取的形参名为 arg0 arg1 ... builder.append(parameters[i].getName()); if (i != parameters.length - 1) { builder.append(", "); } } builder.append(") {"); // 添加方法体的方法 builder.append("System.out.println(\"" + method.getName() + "\");"); // 动态添加return语句 // 获取返回类型的简类名 String returnTypeSimpleName = method.getReturnType().getSimpleName(); if ("void".equals(returnTypeSimpleName)) { } else if ("int".equals(returnTypeSimpleName)) { builder.append("return 111;"); } else if ("String".equals(returnTypeSimpleName)) { builder.append("return \"method return string\";"); } builder.append("}"); // System.out.println(builder); try { // 制造ctClass的方法 CtMethod method1 = CtMethod.make(builder.toString(), ctClass); // 将方法添加到类中 ctClass.addMethod(method1); } catch (CannotCompileException e) { e.printStackTrace(); } }); // 在内存中生成类并将类加载到JVM Class<?> aClass = ctClass.toClass(); // 创建对象(接口的实现类可以进行强转) AccountDao accountDao = (AccountDao) aClass.getDeclaredConstructor().newInstance(); // 调用方法 accountDao.delete(); accountDao.insert(""); accountDao.selectByActno(""); accountDao.update("", 12.0); }
工具类 GenerateDaoProxy 的实现
- 工具类 GenerateDaoProxy 可以动态生成接口的实现类
- 在MyBatis中对javassist进行了二次包装,所以可以在MyBatis中直接使用javassist
- 由于SQL语句的id是框架的使用者提供的,所以框架的开发者不可能知道SQL语句的id,因此框架的开发者就规定SQL语句的id必须时dao接口中的方法名,namespace必须是dao接口的全限定类名,否则不能使用框架提供的动态代理生成接口的实现类的功能
package cw.study.mybatis.utils; import org.apache.ibatis.javassist.CannotCompileException; import org.apache.ibatis.javassist.ClassPool; import org.apache.ibatis.javassist.CtClass; import org.apache.ibatis.javassist.CtMethod; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.session.SqlSession; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.Arrays; /** * ClassName: GenerateDaoProxy * Package: cw.study.mybatis.utils * Description: * 该工具类用于动态生成实现Dao接口的代理类 * GenerateDaoProxy 这个工具类是MyBatis框架提供的 * * @Author tcw * @Create 2023-05-31 17:42 * @Version 1.0 */ public class GenerateDaoProxy { /** * 工具类的构造方法私有化,防止创建对象 */ private GenerateDaoProxy() {} /** * 动态生成Dao接口的代理类对象 * * @param sqlSession 与数据库的会话对象,由工具类的使用这传递 * @param daoInterfaceClass Dao接口 * @return Dao接口的代理类对象 */ public static Object generate(SqlSession sqlSession, Class daoInterfaceClass) { // 获取类池 ClassPool pool = ClassPool.getDefault(); // 制造接口的代理类 CtClass daoInterfaceImpl = pool.makeClass(daoInterfaceClass.getName() + "Impl"); // 制造接口 CtClass daoInterface = pool.makeInterface(daoInterfaceClass.getName()); // 接口的代理类实现接口 daoInterfaceImpl.addInterface(daoInterface); // 接口的代理类实现接口中的方法 // 获取接口中所有的方法 Method[] daoInterfaceClassDeclaredMethods = daoInterfaceClass.getDeclaredMethods(); // 遍历接口中的所有的方法,逐个进行实现,并添加到接口的代理类中 Arrays.stream(daoInterfaceClassDeclaredMethods).forEach(method -> { // 实现接口中的方法 try { // 接口方法的实现方法的代码 StringBuilder methodCode = new StringBuilder(); // public int update(String actno, Double balance) {代码;} methodCode.append("public "); // 获取接口方法的返回值类型,添加到实现方法中 methodCode.append(method.getReturnType().getName()); methodCode.append(" "); // 获取接口方法的方法名,添加到实现方法中 methodCode.append(method.getName()); methodCode.append("("); // 获取接口方法的形参列表,添加到实现方法中 Parameter[] methodParameters = method.getParameters(); for (int i = 0; i < methodParameters.length; i++) { // 获取形参的类型 methodCode.append(methodParameters[i].getType().getName()); methodCode.append(" "); // 获取形参的名 arg0 arg1 arg2 ... methodCode.append(methodParameters[i].getName()); // 如果不是最后一个形参需要在后面添加逗号 if (i != methodParameters.length - 1) { methodCode.append(", "); } } methodCode.append(")"); methodCode.append("{\n"); // 接口方法的具体实现 // 获取与数据库的会话对象 // javassist 需要知道类是哪个包下的所以要使用全限定包名 methodCode.append("\torg.apache.ibatis.session.SqlSession sqlSession = cw.study.mybatis.utils" + ".SqlSessionUtil.openSession();\n"); // 执行SQL语句,我们需要知道SQL语句的类型才可以调用相应的方法执行SQL // getConfiguration() 获取MyBatis核心配置文件中根标签configuration中的内容 // getMappedStatement(SQL语句的Id) 根据SQL语句的id获取相应的SQL语句 // getSqlCommandType() 获取SQL语句的类型,获取到SQL语句的类型是一个枚举值 // 由于SQL语句的id是框架的使用者提供的,所以框架的开发者不可能知道SQL语句的id // 因此框架的开发者就规定SQL语句的id必须时dao接口中的方法名,namespace必须是dao接口的全限定类名 // 否则不能使用框架提供的动态代理生成接口的实现类的功能 // SQL id = namespace + . +SQL id String SqlId = daoInterfaceClass.getName() + "." + method.getName(); SqlCommandType sqlCommandType = sqlSession.getConfiguration().getMappedStatement(SqlId).getSqlCommandType(); // 根据SQL语句的类型的不同调用相应的方法 if (sqlCommandType == SqlCommandType.INSERT) { } else if (sqlCommandType == SqlCommandType.DELETE) { } else if (sqlCommandType == SqlCommandType.UPDATE) { methodCode.append("\treturn sqlSession.update(\"" + SqlId + "\", arg0);\n"); } else if (sqlCommandType == SqlCommandType.SELECT) { // by java.lang.reflect.InvocationTargetException methodCode.append("\treturn (" + method.getReturnType().getName() + ") sqlSession.selectOne(\"" + SqlId + "\", arg0);\n"); } methodCode.append("}"); // System.out.println(methodCode); // 制造接口方法对应的实现方法 CtMethod ctMethod = CtMethod.make(methodCode.toString(), daoInterfaceImpl); // 将制造的实现方法添加到动态生成的代理类中 daoInterfaceImpl.addMethod(ctMethod); } catch (Exception e) { e.printStackTrace(); } }); // 接口动态代理类的对象 Object daoInterfaceProxyObj = null; try { // 在内存中动态生成类,并且将动态生成的类添加到JVM中 Class<?> daoInterfaceImplClass = daoInterfaceImpl.toClass(); // 创建接口代理类的对象 daoInterfaceProxyObj = daoInterfaceImplClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } // 返回接口动态代理类的对象 return daoInterfaceProxyObj; } }
工具类 GenerateDaoProxy 测试
- 要想使用工具类GenerateDaoProxy这种自动生成Dao接口实现类的机制: namespace必须是dao接口的全限定名称,id必须是dao接口的方法名。
<!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
package cw.study.mybatis.pojo; /** * ClassName: Account * Package: cw.study.mybatis.pojo * Description: * * @Author tcw * @Create 2023-05-28 14:33 * @Version 1.0 */ public class Account { private Long id; private String actno; private Double balance; @Override public 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; } }
package cw.study.mybatis.dao; import cw.study.mybatis.pojo.Account; /** * ClassName: AccountDao * Package: cw.study.mybatis.dao * Description: * * @Author tcw * @Create 2023-05-31 16:44 * @Version 1.0 */ public interface AccountDao { Account selectByActno(String actno); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cw.study.mybatis.dao.AccountDao"> <select id="selectByActno" resultType="cw.study.mybatis.pojo.Account"> select * from t_act where actno = #{actno} </select> </mapper>
@org.junit.Test public void testGenerateDaoProxy() { SqlSession sqlSession = SqlSessionUtil.openSession(); AccountDao accountDao = (AccountDao) GenerateDaoProxy.generate(sqlSession, AccountDao.class); Account act001 = accountDao.selectByActno("act001"); System.out.println(act001); }
MyBatis 的 getMapper 方法(MyBatis 的接口代理机制)
- 在MyBatis中提供了相关机制,可以为我们动态生成dao接口的代理实现类,即工具类 GenerateDaoProxy 不用我们编写
- MyBatis中实际上采用了代理机制,在内存中生成dao接口的代理实现类,并创建代理类的实例对象
- 如果要使用MyBatis提供的dao接口代理机制,SQL语句的id必须时dao接口中的方法名,namespace必须是dao接口的全限定类名
- MyBatis提供的dao接口代理机制的使用如下:
@org.junit.Test public void testGetMapper() { SqlSession sqlSession = SqlSessionUtil.openSession(); // GenerateDaoProxy.generate(sqlSession, AccountDao.class); // 需要一个sqlSession用于获取SQL id,AccountDao.class 需要代理实现的接口 // sqlSession.getMapper(AccountDao.class) // 调用该方法的就是用于获取SQL id的sqlSession,AccountDao.class 需要代理实现的接口 // 该方法返回dao接口的代理实现类对象实例 // 要使用该方法,SQL语句的id必须时dao接口中的方法名,namespace必须是dao接口的全限定类名 AccountDao accountDaoProxy = sqlSession.getMapper(AccountDao.class); Account act001 = accountDaoProxy.selectByActno("act001"); System.out.println(act001); }
面向接口进行CRUD
工具类 SqlSessionUtil
package cw.mybatis.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; import java.io.IOException; /** * ClassName: SqlSessionUtil * Package: cw.mybatis.utils * Description: * * @Author tcw * @Create 2023-05-23 21:40 * @Version 1.0 */ public class SqlSessionUtil { private static SqlSessionFactory sqlSessionFactory = null; // 默认使用数据库环境对应的SqlSessionFactory private static ThreadLocal<SqlSession> local = new ThreadLocal<>(); // 保证一个线程对应一个SqlSession static { try { // 获取默认使用数据库环境对应的SqlSessionFactory对象 sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config" + ".xml")); } catch (IOException e) { e.printStackTrace(); } } /** * 私有化构造器,防止创建工具类实例对象 */ private SqlSessionUtil() {} /** * 使用工厂对象开启本线程和数据库的会话 * * @return 与数据库的会话对象 */ public static SqlSession openSession() { SqlSession sqlSession = local.get(); // 获取当前线程对应的数据库会话对象 // 如果当前线程没有对应的数据库会话对象,则创建一个会话对象 if (sqlSession == null) { sqlSession = sqlSessionFactory.openSession(); // 保存本线程对应的数据库会话对象 // 将sqlSession对象绑定到当前线程上。 local.set(sqlSession); } return sqlSession; } /** * 关闭会话对象 * 关闭SqlSession对象并从当前线程中移除SqlSession对象 */ public static void close() { SqlSession sqlSession = local.get(); // 获取当前线程对应的数据库会话对象 // 如果当前线程有相应的数据库会话对象就进行关闭 if (sqlSession != null) { sqlSession.close(); // 注意移除SqlSession对象和当前线程的绑定关系。 // 因为Tomcat服务器支持线程池。也就是说:用过的线程对象t1,可能下一次还会使用这个t1线程。 local.remove(); } } }
Car(pojo)
package cw.mybatis.pojo; /** * ClassName: Car * Package: cw.mybatis.pojo * Description: * 封装汽车相关信息的pojo类,普通的java类。 * * @Author tcw * @Create 2023-05-23 21:59 * @Version 1.0 */ public class Car { private Long id; private String carNum; private String brand; private Double guidePrice; private String produceTime; private String carType; public Car() { } public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) { this.id = id; this.carNum = carNum; this.brand = brand; this.guidePrice = guidePrice; this.produceTime = produceTime; this.carType = carType; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCarNum() { return carNum; } public void setCarNum(String carNum) { this.carNum = carNum; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public Double getGuidePrice() { return guidePrice; } public void setGuidePrice(Double guidePrice) { this.guidePrice = guidePrice; } public String getProduceTime() { return produceTime; } public void setProduceTime(String produceTime) { this.produceTime = produceTime; } public String getCarType() { return carType; } public void setCarType(String carType) { this.carType = carType; } @Override public String toString() { return "Car{" + "id=" + id + ", carNum='" + carNum + '\'' + ", brand='" + brand + '\'' + ", guidePrice=" + guidePrice + ", produceTime='" + produceTime + '\'' + ", carType='" + carType + '\'' + '}'; } }
CarMapper
- 操作数据库的接口,在MyBatis中一般包名命名为mapper,就是MVC架构模式中的dao
- 在MyBatis中操作数据库的接口名,一般叫XxxxMapper,而不为XxxxDao
package cw.mybatis.mapper; import cw.mybatis.pojo.Car; import java.util.List; /** * ClassName: CarMapper * Package: cw.mybatis.mapper * Description: * * @Author tcw * @Create 2023-05-23 21:57 * @Version 1.0 */ public interface CarMapper { /** * 新增 car * * @param car 需要新增的 car 信息 * @return 影响数据库中的条数 */ int insert(Car car); /** * 根据 id 删除汽车信息 * * @param id 汽车信息对应的 id * @return 影响数据库中的条数 */ int deleteById(Long id); /** * 修改汽车信息 * * @param car 修改之后的汽车信息 * @return 影响数据库中的条数 */ int update(Car car); /** * 根据汽车 id 查询汽车信息 * * @param id 汽车信息的 id * @return 汽车信息 */ Car selectById(Long id); /** * 查询所有的汽车信息 * * @return 所有的汽车信息 */ List<Car> selectAll(); }
CarMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 如果要使用面向接口的方式进行CRUD,则namespace的属性值必须为相应接口的全类名 --> <!-- SQL语句的id必须为方法名 --> <mapper namespace="cw.mybatis.mapper.CarMapper"> <insert id="insert"> insert into t_car values(null, #{carNum},#{brand},#{guidePrice},#{produceTime},#{carType}) </insert> <delete id="deleteById"> delete from t_car where id = #{id} </delete> <update id="update"> update t_car set car_num=#{carNum}, brand=#{brand}, guide_price=#{guidePrice}, produce_time=#{produceTime}, car_type=#{carType} where id = #{id} </update> <select id="selectById" resultType="cw.mybatis.pojo.Car"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car where id = #{id} </select> <select id="selectAll" resultType="cw.mybatis.pojo.Car"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car </select> </mapper>
测试
package cw.mybatis.mapper; import cw.mybatis.pojo.Car; import cw.mybatis.utils.SqlSessionUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; import static org.junit.Assert.*; /** * ClassName: CarMapperTest * Package: cw.mybatis.mapper * Description: * * @Author tcw * @Create 2023-05-23 22:15 * @Version 1.0 */ public class CarMapperTest { @Test public void insert() { SqlSession sqlSession = SqlSessionUtil.openSession(); // 面向接口,获取接口的代理对象 CarMapper mapper = sqlSession.getMapper(CarMapper.class); // 数据对应的对象 Car car = new Car(null, "4444", "奔驰C200", 32.0, "2000-10-10", "新能源"); // 调用定义的新增car的方法 int insert = mapper.insert(car); System.out.println(insert); sqlSession.commit(); SqlSessionUtil.close(); } @Test public void deleteById() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); int i = mapper.deleteById(1L); System.out.println(i); sqlSession.commit(); SqlSessionUtil.close(); } @Test public void update() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Car car = new Car(20L, "4444", "奔驰C200&&&", 32.0, "2000-10-10", "新能源"); int update = mapper.update(car); System.out.println(update); sqlSession.commit(); SqlSessionUtil.close(); } @Test public void selectById() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Car car = mapper.selectById(20L); System.out.println(car); SqlSessionUtil.close(); } @Test public void selectAll() { SqlSession sqlSession = SqlSessionUtil.openSession(); List<Car> cars = sqlSession.getMapper(CarMapper.class).selectAll(); cars.forEach(System.out::println); SqlSessionUtil.close(); } }