反射

反射的基本使用与封装

  • User.java ```java package com.cy.hu;

public class User { private String name; private Integer age; //name和age的get和set方法不显示了,占位置 @Override public String toString() { return “User{“ + “name=’” + name + ‘\’’ + “, age=” + age + ‘}’; } }

  1. - 封装的通过反射获得类的实例的Util
  2. ```java
  3. package com.cy.util;
  4. public class ReflectUtil {
  5. /**
  6. * 基于传入的类型构建对象实例
  7. * packageClass表示 包路径.类名
  8. */
  9. public static Object newInstance(String packageClass,
  10. Object args[],Class<?>...parameterTypes) throws Throwable {
  11. Class<?> aClass = Class.forName(packageClass);
  12. Constructor<?> constructor = aClass.getDeclaredConstructor(parameterTypes);
  13. constructor.setAccessible(true);//不是同包下,设置权限
  14. Object o = constructor.newInstance(args);
  15. return o;
  16. }
  17. }
  • 反射使用 ```java package com.cy.hu; import com.cy.util.ReflectUtil; import javax.jws.Oneway; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;

public class Test { public static void main(String[] args) throws Throwable { //构建对象(传统方式),编译时确定构建对象方式(对象构建时需要构造方法) Object oo = new Object();

  1. //构建对象(反射方式-API->不能预知未来,但可以驾驭未来)
  2. //反射的起点是谁?Class类型的对象
  3. //如何获取Class类型的对象呢?(Class类型的对象又称之为字节码对象,一个JVM只能有一份,单例)
  4. //方式1,通过类名.class方式
  5. Class<?> c1 = Object.class;//需要在编译时就知道Object类
  6. //方式2,通过对象实例.getClass方式
  7. Class<?> c2 = new Object().getClass();//需要在编译时就知道Object类
  8. //方式3,通过Class.forName的方式,优先选择这种
  9. Class<?> c3 = Class.forName("java.lang.Object");
  10. System.out.println(c1==c2);//true
  11. System.out.println(c2==c3);//true
  12. //通过字节码对象获取无参构造方法对象
  13. Constructor<?> constructor = c3.getDeclaredConstructor();
  14. //通过构造方法对象构建类的实例对象
  15. Object o1 = c1.newInstance(); //o1和o3获得的对象方式都可以
  16. Object o3 = constructor.newInstance();
  17. System.out.println("----------------------------------");
  18. //1.通过反射构建User类型的实例对象
  19. //1.1获得反射应用的起点对象(类的字节码对象)
  20. Class<?> aClass = Class.forName("com.cy.hu.User");
  21. //1.2基于字节码对象获取类的构造方法对象
  22. Constructor<?> con = aClass.getDeclaredConstructor(String.class, Integer.class);
  23. //1.3获得实例对象
  24. Object o = con.newInstance("iu", 18);
  25. System.out.println(o);
  26. //通过封装的ReflectUtil获得实例对象
  27. Object o2 = ReflectUtil.newInstance("com.cy.hu.User", new Object[]{"iu", 23}, String.class, Integer.class);
  28. System.out.println(o2);
  29. //2.通过反射为User类实例的属性直接赋值
  30. Field name = aClass.getDeclaredField("name");
  31. name.setAccessible(true);
  32. name.set(o,"hu");
  33. Field age = aClass.getDeclaredField("age");
  34. age.setAccessible(true);
  35. age.set(o, 19);
  36. System.out.println(o);
  37. //3.通过反射调用User类的set方法为属性赋值
  38. Method setAge = aClass.getDeclaredMethod("setAge", Integer.class);
  39. setAge.setAccessible(true);
  40. setAge.invoke(o, 23);
  41. System.out.println(o);
  42. //4.通过反射调用User类的get方法获取属性值.
  43. Method getAge = aClass.getDeclaredMethod("getAge");
  44. Object getResult = getAge.invoke(o);
  45. System.out.println(getResult);
  46. }

}

  1. <a name="JzJv5"></a>
  2. ### 注解与反射对象
  3. - 判断类上是否有指定注解,有就给它反射实例对象
  4. ```java
  5. package com.cy.java.api.reflect;
  6. import java.lang.annotation.*;
  7. /**自定义注解
  8. * @Retention 注解用于描述定义的注解何时有效(运行时,编译时)
  9. * @Target 注解用于描述这个注解可以描述哪些成员(类,属性,方法)
  10. * */
  11. @Retention(RetentionPolicy.RUNTIME)
  12. @Target(ElementType.TYPE)
  13. @interface Component{ //@interface 描述的类型为注解类型(本质上是一个特殊的class)
  14. }
  15. @Component
  16. class classA{
  17. }
  18. public class AnnotationTests {
  19. public static void main(String[] args) throws Exception {
  20. //检查classA 上是否有@Component注解描述
  21. //1.获取类的字节码对象
  22. Class<?> aClass = Class.forName("com.cy.java.api.reflect.classA");
  23. //2.判定对象上是否有@Component注解
  24. boolean flag = aClass.isAnnotationPresent(Component.class);
  25. System.out.println(flag);//true
  26. if(flag){
  27. Object o = aClass.newInstance();
  28. System.out.println(o);
  29. }
  30. //还可以采用如下方式判定类上是否有指定注解,Annotation类型是所有注解的父类类型
  31. Annotation annotation= aClass.getAnnotation(Component.class);
  32. if(annotation!=null){
  33. Object oo = aClass.newInstance();
  34. System.out.println(oo);
  35. }
  36. }
  37. }

反射获得当前类所在包下全部类

  • 可以应用在包扫描,给所有包下类建立实例对象

    1. package com.cy.java.api.reflect;
    2. import java.io.File;
    3. import java.net.URL;
    4. public class PackTests {
    5. public static void main(String[] args) throws Exception {
    6. //获取类的字节码对象
    7. Class<?> aClass = Class.forName("com.cy.java.api.reflect.PackTests");
    8. //获取类所在的包对象
    9. Package pack = aClass.getPackage();
    10. //获得包名
    11. String packName = pack.getName();
    12. System.out.println(packName);// com.cy.java.api.reflect
    13. //将包结构转换为目录结构
    14. String dirName = packName.replace(".", "/");
    15. System.out.println(dirName);// com/cy/java/api/reflect
    16. //通过类加载器获取目录结构dirName对应的绝对路径
    17. URL url = ClassLoader.getSystemClassLoader().getResource(dirName);
    18. System.out.println(url); // file:/E:/TCGBIll/CODE/Pro1/out/production/01-javase/com/cy/java/api/reflect
    19. //获取路径对应的文件File对象
    20. System.out.println(url.getPath());// /E:/TCGBIll/CODE/Pro1/out/production/01-javase/com/cy/java/api/reflect
    21. File file = new File(url.getPath());
    22. String[] lists = file.list();
    23. for (String list : lists) {
    24. System.out.print(list+"===");
    25. }// AnnotationTests.class===classA.class===Component.class===PackTests.class===
    26. }
    27. }

    反射具体应用?

    1)获取构造方法对象(Constructor),基于构造方法对象构建类的实例对象?
    为什么不直接new呢?
    2)获取类中属性(Field),进而获取属性值或为属性赋值.
    3)获取类中的方法(Method),并通过反射技术调用方法.
    4)获取类上的注解(Annotation),进而获取注解中内容.
    5)获取类所在包,基于包找到指定包下的类,
    6)……………….

    SpringBoot项目

  • 基于spring技术实现的一个脚手架

  • 为了快速构建项目开发环境
  • springboot提供了开箱即用的特性-依赖,自动配置,…

    SpringBoot初始化

    image.png

  • src/main/java下 java业务代码

  • src/main/resource下 项目配置文件,静态资源
  • srctest/java下 单元测试代码
  • pom.xml 服务端依赖,maven插件配置
  • pom.xml

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <!--parent工程中提供了很多项目的基础依赖-->
    6. <parent>
    7. <groupId>org.springframework.boot</groupId>
    8. <artifactId>spring-boot-starter-parent</artifactId>
    9. <version>2.3.8.RELEASE</version>
    10. <relativePath/> <!-- lookup parent from repository -->
    11. </parent>
    12. <!--我们自己的当前项目的坐标-->
    13. <groupId>com.cy</groupId>
    14. <artifactId>04-springboot-notice</artifactId>
    15. <version>0.0.1-SNAPSHOT</version>
    16. <name>04-springboot-notice</name>
    17. <description>Demo project for Spring Boot</description>
    18. <!--项目属性的配置(jdk的版本,将来还可以自己定义依赖的版本)-->
    19. <properties>
    20. <java.version>1.8</java.version>
    21. </properties>
    22. <dependencies>
    23. <!--springboot 工程的启动依赖-->
    24. <dependency>
    25. <groupId>org.springframework.boot</groupId>
    26. <artifactId>spring-boot-starter</artifactId>
    27. </dependency>
    28. <!--springboot 工程中的单元测试依赖-->
    29. <dependency>
    30. <groupId>org.springframework.boot</groupId>
    31. <artifactId>spring-boot-starter-test</artifactId>
    32. <scope>test</scope>
    33. <exclusions>
    34. <!--排除一些不需要的依赖-->
    35. <exclusion>
    36. <groupId>org.junit.vintage</groupId>
    37. <artifactId>junit-vintage-engine</artifactId>
    38. </exclusion>
    39. </exclusions>
    40. </dependency>
    41. </dependencies>
    42. <build>
    43. <!--项目构建或打包时候需要的一些依赖-->
    44. <plugins>
    45. <!--假如当前插件显示红色,可以为其指定version-->
    46. <plugin>
    47. <groupId>org.springframework.boot</groupId>
    48. <artifactId>spring-boot-maven-plugin</artifactId>
    49. <version>2.3.8.RELEASE</version>
    50. </plugin>
    51. </plugins>
    52. </build>
    53. </project>

主类项目启动

  1. 通过ClassLoader(类加载器-负责将磁盘中的类读到内存中)将指定包中的类加载到内存
  2. 通过线程(thread)调用io(InputStream)从磁盘(Disk)读取文件(File)信息
  3. 如果读取到某个类是在主类的包或者子包下,且存在基于类上的描述(@Component,@Service,@Controller,…..)
    • 通过前面的反射获取当前类所在包下的全部类、注解与反射现象得到两个条件都具备的类
    • 然后读取类上的描述(@Component,@Service,@Controller,…..),并基于描述构建配置对象(BeanDefinition),存储类的配置信息(类全名,作用域,….).
  4. 基于类的配置信息通过Bean工厂反射构建类的实例(对象),并进行存储(对象池-用时从池中取)

image.png

  1. package com.cy;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import java.util.Arrays;
  5. /**
  6. * 启动类:由@SpringBootApplication注解描述
  7. * 启动类在运行时都会做什么呢?
  8. * 1)通过ClassLoader(类加载器-负责将磁盘中的类读到内存中)将指定包中的类加载到内存.
  9. * 2)通过线程(thread)调用io(InputStream)从磁盘(Disk)读取文件(File)信息.
  10. * 3)读取类上的描述(@Component,@Service,@Controller,.....),并基于描述构建
  11. * 配置对象(BeanDefinition),存储类的配置信息(类全名,作用域,....).
  12. * 4)基于类的配置信息通过Bean工厂反射构建类的实例(对象),并进行存储(对象池-用时从池中取)
  13. * 5)当我们需要一个类的实例时可以从对象池(Bean池)获取即可.
  14. * JVM 参数分析
  15. * 1)检测类的加载:-XX:+TraceClassLoading
  16. */
  17. @SpringBootApplication
  18. public class NoticeApplication {
  19. public static void main(String[] args) {
  20. //System.out.println(Arrays.toString(args));
  21. SpringApplication.run(NoticeApplication.class, args);
  22. }
  23. /**
  24. * 记住(规则):我们要交给spring容器管理的对象,一定要放在启动类所在包或子包中,
  25. * 然后使用特性注解进行描述(@Component,@Service,....)
  26. *
  27. * FAQ?
  28. * Spring是一个资源管理框架,请问资源是谁?对象
  29. */
  30. }

Mybatis

HikariCP连接池测试链接数据库

  • Java中连接池规范 (DataSource)

1)为什么要创建连接池?(连接的创建和销毁非常耗时-TCP/IP-3次握手,4次挥手)
2)java中连接池的规范?(javax.sql.DataSource)
3)java中连接池的江湖?(c3p0,dbcp,Druid,hikariCP,…)
4)连接池设计思考?(数据存储结构,算法,线程安全,参数设计,…)

  • 池化思想
    • 所有池的设计都会用到一种设计模式:享元模式 (通过池复用对象)
  • 添加依赖 ```xml mysql mysql-connector-java runtime

org.springframework.boot spring-boot-starter-data-jdbc

  1. - 添加数据库连接配置
  2. - spring.datasource.url=jdbc:mysql:///sys_notice?serverTimezone=GMT%2B8
  3. - spring.datasource.username=root
  4. - spring.datasource.password=tarena
  5. - 测试连接池HikariCP连接
  6. - 测试连接池HikariCP插入数据
  7. - 测试连接池HikariCP查询数据
  8. - 连接池的测试应用流程?
  9. - 添加依赖?(mysql驱动,spring-jdbc依赖)
  10. - 连接数据库的配置(url,username,password)
  11. - 构建单元测试类及方法对连接池进行单元测试?(获取连接)
  12. - 连接获取原理分析?(@Test->DataSource->HikariDataSource->HikariPool->.....
  13. ```java
  14. package com.cy.pj.sys.dao;
  15. /**
  16. * 通过此单元测试类获取数据源对象,并且通过数据对象获取数据库连接
  17. * @SpringBootTest 注解描述的类,为springboot中的单元测试类
  18. * 说明:
  19. * 1)springboot中的单元测试类必须放在启动类所在包,或子包中
  20. * 2)springboot中的单元测试类必须使用@SpringBootTest注解描述
  21. */
  22. @SpringBootTest
  23. public class DataSourceTests {
  24. /**
  25. * 在项目中添加了数据库相关依赖以后,springboot底层会自动帮我们配置一个数据源(DataSource)对象,此对象是连接池的规范.
  26. * @Autowired注解描述属性时,是告诉spring框架,要基于反射机制为属性赋值(依赖注入)
  27. * 赋值时,首先会基于属性类型从spring容器查找相匹配的对象, 假如只有一个则直接注入,
  28. * 有多个相同类型的对象时,还会比较属性名(检测属性名是否与bean名字相同),有相同的则直接注入(没有相同的直接抛出异常.)
  29. */
  30. @Autowired
  31. private DataSource dataSource; //HikariDataSource (类),依赖注入
  32. @Test
  33. void testGetConnection() throws SQLException {
  34. //获取链接时,会基于dataSource规范获取连接池对象,进而从池中获取连接
  35. Connection conn = dataSource.getConnection();
  36. System.out.println("conn="+conn);
  37. }
  38. @Test
  39. void testSaveNotice() throws SQLException {
  40. //获得连接HikariCP连接池提供的连接,Hikari底层封装了注册驱动,将连接返回
  41. Connection connection = dataSource.getConnection();
  42. //建立sql语句
  43. String sql = "insert into sys_notice(title,type,content,status,createdUser,createTime,modifiedUser,modifiedTime,remark) values (?,?,?,?,?,?,?,?,?) ";
  44. //创建处理sql对象,设置占位符的值
  45. PreparedStatement preStmt = connection.prepareStatement(sql);//预编译方式创建Statement
  46. preStmt.setObject(1, "放假通知");
  47. preStmt.setObject(2, "1");
  48. preStmt.setObject(3,"放假100天");
  49. preStmt.setObject(4,0);
  50. preStmt.setObject(5,"hu");
  51. preStmt.setObject(6,new Date(System.currentTimeMillis()));
  52. preStmt.setObject(7,"iu");
  53. preStmt.setObject(8,new Date(System.currentTimeMillis()));
  54. preStmt.setObject(9,"100天以后去见IU");
  55. //将sql语句送到数据库执行
  56. boolean flag = preStmt.execute();
  57. //方法执行返回值为true表示处理的是一个不为null的结果集,为false表示增删改,或者结果集为null
  58. System.out.println(flag);
  59. //释放资源
  60. preStmt.close();
  61. connection.close();
  62. }
  63. @Test
  64. void testSelectNotices() throws SQLException {
  65. Connection connection = dataSource.getConnection();
  66. String sql = "select * from sys_notice where id>=?";
  67. PreparedStatement ptStmt = connection.prepareStatement(sql);
  68. ptStmt.setObject(1, 2);
  69. boolean flag = ptStmt.execute();
  70. ResultSet rs = null;
  71. if(flag){
  72. rs = ptStmt.getResultSet();
  73. List<Map<String,Object>> list = new ArrayList<>();
  74. //获取结果集中的元数据(表名、字段名)
  75. ResultSetMetaData rsmd = rs.getMetaData();
  76. while (rs.next()){
  77. //一行记录为一个map对象
  78. Map<String,Object> map = new HashMap<>();//将来也可以使用pojo
  79. /*for (int i = 1; i <=rsmd.getColumnCount() ; i++) {
  80. map.put(rsmd.getColumnLabel(i), rs.getObject(i));
  81. } 这种方式也可以*/
  82. //取出类中的数据存储到map(key为字段名,值是字段value)
  83. for (int i = 1; i <=rsmd.getColumnCount() ; i++) {
  84. map.put(rsmd.getColumnName(i),rs.getObject(i));
  85. }
  86. System.out.println(map);
  87. list.add(map);
  88. }
  89. //System.out.println(list);
  90. }
  91. //关闭资源
  92. rs.close();
  93. ptStmt.close();
  94. connection.close();
  95. }
  96. }

image.png

Mybatis框架简介

  • mybatis是一个用于简化jdbc操作的持久层框架
  • mybatis:简单,灵活,开源,稳定,功能强大-的SQL定制,参数映射,结果映射
    • JDBC编程过程的问题分析
      • 步骤固定(写几次过后,谁都会,没有必要反复写)
      • 占位符参数赋值代码简单,但需要重复编写.
      • 行映射过程代码比较简单,但是需要的代码量比较大,需要反复编写
      • SQL语句不够灵活(不支持分支、循环结构,很难基于条件进行动态SQL的定制)
    • mybatis支持标签、支持分支和循环结构,更加灵活,大大减少了重复代码的编写
  • SpringBoot工程中的mybatis应用环境搭建

    • 添加依赖(mybatis):官网http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
    • 初始配置(事务超时,驼峰命名,映射文件路径)
    • mybatis.mapper-locations=classpath:/mapper//.xml
    • 对环境进行单元测试(重点检查通过sqlsession对象是否可以获取数据库的链接)
      • 说明:SqlSession对象获取的链接其实来自于连接池(HikariCP)
    • 添加持久层增删改查操作,并对操作进行测试,以后面若依公告子系统项目进行mybatis的操作理解

      Mybatis使用流程

  • 添加依赖

    1. <dependency>
    2. <groupId>org.mybatis.spring.boot</groupId>
    3. <artifactId>mybatis-spring-boot-starter</artifactId>
    4. <version>2.1.3</version>
    5. </dependency>
  • Mybatis 简易配置application.properties ```java

    spring mybatis

    配置sql超时

    mybatis.configuration.default-statement-timeout=30

驼峰命名规则

mybatis.configuration.map-underscore-to-camel-case=true

映射文件路径

mybatis.mapper-locations=classpath:/mapper//.xml

日志

logging.level.com.cy=debug

  1. - 流程
  2. - mybatis封装了jdbc和数据库连接池Hikari
  3. - 在对持久层数据插入的测试中,SysNoticeDaoTests类里面定义了一个属性SysNoticeDao,且属性上有@Mapper注解,那么这个属性的值是交给SpringIOC容器管理,它的实现类是一个代理类,然后利用反射创建的代理对象放到IOC容器中,在属性定义时,spring框架从IOC容器的bean池中DL(依赖查找)与属性对应的对象, DI(依赖注入)到添加了@Autowired注解的属性属性....代理对象底层有SqlSession属性。
  4. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/358364/1611843801513-98fff9e4-daf1-40bb-9079-f4f4abfdbd67.png#align=left&display=inline&height=398&margin=%5Bobject%20Object%5D&name=image.png&originHeight=463&originWidth=867&size=46653&status=done&style=none&width=746)
  5. - 代理对象的SqlSession会话对象通过命名空间.方法Id找到mapper映射文件具体的操作,也就获得了sql语句,操作sql
  6. ```java
  7. package com.cy.pj.sys.dao;
  8. import com.cy.pj.sys.pojo.SysNotice;
  9. import org.apache.ibatis.session.SqlSession;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. /**@Repository注解由spring框架提供,用于描述数据逻辑对象,
  12. * 同样这样的对象会交给spring去管理,是spring容器中的一个bean*/
  13. //@Repository
  14. public class SysNoticeDaoProxy {//模拟mybatis为Dao接口产生的实现类
  15. @Autowired
  16. private SqlSession sqlSession;
  17. public int insertNotice(SysNotice notice){
  18. String statement = "com.cy.pj.sys.dao.SysNoticeDao.insertNotice";
  19. //数据持久化(底层会基于statement找到对象的sql)
  20. int count = sqlSession.insert(statement, notice);
  21. return count;
  22. }
  23. }
  • 依靠映射文件、mybatis配置文件、数据源(连接池),SqlSessionFactoryBuild会创建接口SqlSessionFactory的实现类来创建操作数据库的会话对象,这个会话对象同样是实现了接口SqlSession,会话对象通过调用JDBC的API来通过sql语句操控数据库

image.png

  • 会话对象有着DateSource数据源属性(数据库连接池规范),此时mybatis封装的HikariCP连接池对象会被注入到这个属性(规范)中,如果连接池没有连接,那么就会去连接数据库获得连接,会去找JDBC规范,此时Mysql Driver数据库驱动会被注入到jdbc规范中,然后就去与数据库连接,就可以获得数据库的连接了,就可以操控数据库了…………………sqlsession对象获得数据库连接

image.png

  1. package com.cy.pj.sys.dao;
  2. import org.apache.ibatis.session.SqlSession;
  3. import org.junit.jupiter.api.Test;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import java.sql.Connection;
  7. @SpringBootTest
  8. public class MyBatisTests {
  9. /**
  10. * SqlSession是mybatis框架中实现与数据库进行会话的入口对象。
  11. * 假如我们可以通过此对象获取与数据库的连接,表示可以通过
  12. * mybatis框架实现与数据库会话。
  13. */
  14. @Autowired
  15. private SqlSession sqlSession;//这里的sqlSession指向的对象是谁?(SqlSessionTemplate)
  16. @Test
  17. void testGetConnection(){
  18. //连接来自哪里?(来自于连接池-底层会自动将连接池注入给mybatis框架)
  19. Connection connection = sqlSession.getConnection();
  20. System.out.println("conn="+connection);
  21. }
  22. }

jdbc-select.png

mybatis总结

  • mybatis是一个用于简化jdbc操作的持久层框架
  • mybatis:简单,灵活,开源,稳定,功能强大-的SQL定制,参数映射,结果映射
    • JDBC编程过程的问题分析
      • 步骤固定(写几次过后,谁都会,没有必要反复写)
      • 占位符参数赋值代码简单,但需要重复编写.
      • 行映射过程代码比较简单,但是需要的代码量比较大,需要反复编写
      • SQL语句不够灵活(不支持分支、循环结构,很难基于条件进行动态SQL的定制)
    • mybatis支持标签、支持分支和循环结构,更加灵活,大大减少了重复代码的编写
  • MyBatis 框架核心API?(SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession….)
  • MyBatis 框架API会话应用的执行过程?
    • SqlSession->DataSource-Connection-JDBCAPI-SQL
  • SpringBoot工程中的mybatis应用环境搭建
  • 初始配置(事务超时,驼峰命名,映射文件路径)
  • MyBatis 中的动态SQL应用,参数表达式#{}

FAQ

  • @Mapper注解的作用是什么?
    • 告诉spring框架,这个接口的实现类对象由IOC容器创建管理
  • DAO中方法参数为什么有时需要使用@Param注解描述?
    • 版本低了,可能需要这个注解传递参数
    • 如接口方法中fun(@Param(“list”) List list )
      • 传递参数list集合到xml中操作
  • 什么情况下将sql映射写到dao方法上?(推荐简单sql)
    • 简单sql可以通过注解的方式直接写在方法上
  • SQL映射中什么请求下会使用resultType?(简单查询)
    • 简单查询,实体类与数据表里的字段相对于的,都可以用resultType
    • 复杂的一对一,多对多查询,可以采用resultMap
  • 动态sql的语法结构是怎样的?(参考官网-https://mybatis.org/mybatis-3)
  • ……………………………..