MyBatis 01:入门

MyBatis 01:入门

1.概述

三层架构

  • 界面层(User Interface layer):接受用户的数据,显示请求的处理结果。---SpringMVC-----controller包 (servlet)
  • 业务逻辑层(Business Logic Layer):接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据----Spring----service 包(XXXService类)
  • 数据访问层(Data access layer):实现对数据库的增、删、改、查。将数据库的数据提交给业务层,同时将业务层处理的数据保存到数据库---MyBatis----dao包(XXXDao类)

何为框架?

整个或部分系统的可重用设计,一组抽象构件及构件实例间交互的方法;

开发者定制的应用骨架、模板;

安全的,可复用的,不断升级的软件。

何为 MyBatis?

MyBatis ,基于 java 的持久层框架,内部封装 jdbc,开发只需关注 sql 语句而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程;通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

提供sql语句--mybatis处理sql---得到List集合或java对象(表中的数据)

2.基本操作

2.1 流程

1.创建 mysql 数据库和表

2.创建 maven 工程

3.pom.xml 加入 maven 坐标;加入 maven 插件

<dependencies>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
</dependencies>

<build>
    <resources>
      <resource>
          <!--所在的目录-->
          <directory>src/main/java</directory>
          <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          	<include>**/*.properties</include>
          	<include>**/*.xml</include>
          </includes>
          <filtering>false</filtering>
      </resource>
    </resources>

    <plugins>
      <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.1</version>
          <configuration>
          	<source>1.8</source>
          	<target>1.8</target>
          </configuration>
      </plugin>
    </plugins>

</build>

4.建立Dao,不需要实现

5.Dao 接口 Mapper 映射文件

  • dao 包中创建文件xml
  • 文件名称和接口 Dao 一样
<!--
 namespace:必须有值,自定义的唯一字符串
 推荐使用:dao 接口的全限定名称
-->
<mapper namespace="com.fremont.dao.StudentDao">
    <!--
    <select>: 查询数据, 标签中必须是 select 语句
    	id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称,
    	使用名称表示要执行的 sql 语句
    	resultType: 查询语句的返回结果数据类型,使用全限定类名
    -->
    <select id="selectStudents" resultType="com.fremont.domain.Student">
        <!--要执行的 sql 语句-->
        select id,name,email,age from student
    </select>
</mapper>

6.创建MyBatis主配置文件

  • src/main 下创建 resources 目录
  • 创建主配置文件 mybatis.xml
<configuration>
    <!--配置 mybatis 环境-->
    <environments default="mysql">
        <!--id:数据源的名称-->
        <environment id="mysql">
            <!--配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚)-->
            <transactionManager type="JDBC"/>
            <!--数据源 dataSource:创建数据库 Connection 对象
            type: POOLED 使用数据库的连接池
            -->
            <dataSource type="POOLED">
                <!--连接数据库的四个要素-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--支持中文加上 ?useUnicode=true&characterEncoding=utf-8-->
                <property name="username" value="root"/>
                <property name="password" value="fremont"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--告诉 mybatis 要执行的 sql 语句的位置-->
        <mapper resource="com/fremont/dao/StudentDao.xml"/>
    </mappers>
</configuration>

7.测试使用

public class MyBatisTest {
    @Test
    public void testStart() throws IOException {
        //1.mybatis 主配置文件
        //目录从 target/classes 开始
        String config = "mybatis.xml";
        //2.读取配置文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建 SqlSessionFactory 对象,目的是获取 SqlSession
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //4.获取 SqlSession,SqlSession 能执行 sql 语句
        SqlSession session = factory.openSession();
        //5.执行 SqlSession 的 selectList()
        List<Student> list = session.selectList("com.fremont.dao.StudentDao.selectStudents");
        //6.循环输出查询结果
        list.forEach(s -> System.out.println(s));
        //7.关闭 SqlSession,释放资源
        session.close();
    }
}

8.配置日志

mybatis.xml 文件加入日志配置,在控制台输出执行的 sql 语句和参数

<settings>
     <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

2.2 CRUD

在dao的xml配置文件中配置sql语句

<mapper namespace="com.fremont.dao.StudentDao">
    <!--要执行的 sql 语句-->
    <select id="selectStudents" resultType="com.fremont.domain.Student">
        select id,name,email,age from student
    </select>
    
    <insert id="insertStudent">
 		insert into student(id,name,email,age) values(#{id},#{name},#{email},#{age})
	</insert>
    
    <update id="updateStudent">
 		update student set age = #{age} where id=#{id}
	</update>
    
    <delete id="deleteStudent">
 		delete from student where id=#{studentId}
	</delete>
    
</mapper>

2.3 对象分析

2.3.1 对象

Resources 类

  • 用于读取资源文件
  • 有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象

SqlSessionFactoryBuilder 类

  • SqlSessionFactoryBuilder对象的build() 方法创建SqlSessionFactory工厂对象
  • 创建完工厂对象后,就完成了其使命,即可被销毁
  • 一般将该 SqlSessionFactoryBuilder 对象创建为局部对象

SqlSessionFactory 接口

  • 重量级对象(系统开销大),线程安全,一个应用只需要一个该对象
  • 创建 SqlSession使用 SqlSessionFactory 接口openSession()方法
    • openSession(true):创建一个有自动提交功能的 SqlSession
    • openSession():默认false 创建一个非自动提交功能的 SqlSession,需手动提交

SqlSession 接口

  • SqlSession 接口对象用于执行持久化操作
    • selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
  • SqlSession对应数据库会话:以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束
  • SqlSession 接口对象是线程不安全会话结束前,需要马上调用close()方法
  • SqlSession 在方法内部创建,使用完毕后关闭

2.3.2 工具类

MyBatisUtil 类

public class MyBatisUtil {
    //定义 SqlSessionFactory
    private static SqlSessionFactory factory = null;

    static {
        //使用 静态块 创建一次 SqlSessionFactory
        try {
            String config = "mybatis.xml";
            //读取配置文件
            InputStream in = Resources.getResourceAsStream(config);
            //创建 SqlSessionFactory 对象
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (Exception e) {
            factory = null;
            e.printStackTrace();
        }
    }

    /* 获取 SqlSession 对象 */
    public static SqlSession getSqlSession() {
        SqlSession session = null;
        if (factory != null) {
            session = factory.openSession();
        }
        return session;
    }
}

2.4 传统Dao开发

实现dao

public List<Student> selectStudents() {
 	SqlSession session = MyBatisUtil.getSqlSession();
 	List<Student> studentList = session.selectList("com.bjpowernode.dao.StudentDao.selectStudents");
 	session.close();
 	return studentList;
}
public int insertStudent(Student student) {
 	SqlSession session = MyBatisUtil.getSqlSession();
 	int nums = session.insert("com.bjpowernode.dao.StudentDao.insertStudent",student);
 	session.commit();
 	session.close();
 	return nums;
}
  • 真正进行操作的是由框架通过 mapper 中的 SQL 完成的
  • 所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句
  • Mapper 的动态代理方式

3.MyBatis代理Dao

  • mybatis的动态代理: mybatis根据 dao的方法调用,获取执行sql语句的信息
  • mybatis根据dao接口,创建出一个dao接口的实现类, 并创建这个类的对象
  • 完成SqlSession调用方法, 访问数据库

3.1 Dao代理实现

getMapper 获取代理对象

/**
* 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
* getMapper能获取dao接口对应的实现类对象。
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println("dao=" + dao.getClass().getName());

3.2 参数

parameterType

  • mapper文件中属性,属性是可选的
  • dao接口中方法的参数数据类型
  • 类型的完全限定名或别名

简单类型

  • java的基本数据类型和String
  • mapper文件获取简单类型参数值,#{任意字符}占位符
  • 占位符和方法的参数名无关

多个参数

  • @Param命名参数
//接口
public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age);
/*mapper文件
<select id="selectMultiParam" resultType="com.fremont.domain.Student">
	select * from student where name=#{myname} or age=#{myage}
</select>
*/
  • 使用java对象:传入对象,每一个属性就是一个参数
/*创建查询参数对象
vo: value object , 放一些存储数据的类。
	比如 提交请求参数 name ,age ;把name ,age 传给一个service 类
vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。
pojo: 普通的有set, get方法的java类。 普通的java对象
entity(domain域): 实体类, 和数据库中的表对应的类
*/
List<Student> selectMultiObject(QueryParam queryParam);
/*mapper 文件:
完整格式:#{ 属性名,javaType=java数据类型名,jdbcType=数据类型名称 }
一般:#{ 属性名 }
<select id="selectMultiObject"resultType="com.fremont.domain.Student">
 	select id,name,email,age from student 
 	where name=#{queryName} or age=#{queryAge}
</select>
*/
  • 按参数位置: #{ arg 位置 i } 例如 #{ arg 0 }、#{ arg 1 }
  • 使用Map:
    • Map<String,Object> data 格式:
    • List selectMultiMap(Map<String,Object> map);
    • mapper 文件使用 # { key } 引用参数
  • #占位符:使用 PrepareStatement 对象执行 sql 语句,首选
  • $ 字符串替换:用 Statement 把 sql 语句和${}的内容连接起来
//替换表名,列名,不同列排序等操作
Student findByDiffField(
    @Param("col") String colunName,@Param("cval") Object value);
<select id="findByField" resultType="com.xxx.domain.Student">
 	select * from student where ${col} = #{cval}
</select>
  • #和 $区别
  1. 使用 ?在sql语句中占位的, 使用PreparedStatement执行sql,效率高

  2. 能够避免sql注入,更安全

  3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  4. $有sql注入的风险,缺乏安全性
  5. $:可以替换表名或者列名

3.3 封装MyBatis结果

resultType

  • 执行 sql 得到 ResultSet 转换的类型:
    • mybatis调用类的无参数构造方法,创建对象
    • mybatis把ResultSet指定列值付给同名的属性,使用set方法
  • 类型的完全限定名或别名
  • 返回的是集合,应设置为集合包含的类型
  • resultType 和 resultMap,不能同时使用
<!--简单类型/对象类型
 Map:推荐使用 Map<Object,Object>
 	Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录
Map<Object,Object> selectReturnMap(int id);
-->
<select id="selectReturnMap" resultType="java.util.HashMap">
 	select name,email from student where id = #{studentId}
</select>
<!--自定义类型别名:
mybatis主配置文件中定义
-->
<typeAliases>
    <typeAlias type="com.fremont.domain.Student" alias="Stu"/>
    <!--指定包后可以直接使用类名-->
    <package name="com.fremont.domain"/>    
</typeAliases>

resultMap

  • 自定义 sql 的结果和 java 对象属性的映射关系
  • 常用在列名和 java 对象属性名不一样的情况
<!-- mapper 创建 resultMap
 	id:自定义的唯一名称,在<select>使用
 	type:期望转为的 java 对象的全限定名称或别名 
--> 
<resultMap id="studentMap" type="com.fremont.domain.Student">
 	<!-- 主键字段使用 id -->
 	<id column="id" property="id" />
 	<!--非主键字段使用 result-->
 	<result column="name" property="name"/>
 	<result column="email" property="email" />
 	<result column="age" property="age" />
</resultMap>

<!--resultMap: resultMap 标签中的 id 属性值--> 
<select id="selectUseResultMap" resultMap="studentMap">
 	select id,name,email,age from student where name=#{queryName} or 
age=#{queryAge}
</select>

实体类属性名和列名不同

  • 使用列别名和resultType
  • 使用resultMap

3.4 模糊查询

java 代码中给查询数据加上“%”:传入字符串含有%

mapper 文件 sql 语句条件位置加上“%”:like name "%" #{xxx} "%"

上一篇:Processing和Arduino互相通讯的方法


下一篇:记录Union和Union All一些总结