对于MyBatis框架的学习

2023-05-16

1.MyBatis

​ MyBatis 它是Apache的一个开源项目-iBatis , 2010年这个项目由apache software foundation 迁 移到了google code,并且改名为MyBatis 2013年11月迁移到Github。


1.概述

MyBatis是一款优秀的持久化框架,支持自定义SQL,存储过程以及高级映射,MyBatis免去了几乎所有的JDBC代码 以及设置参数,获取结果集对象的工作。MyBatis可以通过简单的XML配置或注解来配置映射关系。

Hibernate框架:全自动映射ORM框架

ORM: Object Relation Mapping 对象关系映射,简单说就是把数据库表和实体类的属性对应起来,让我们可以操作实体类就可以实现操作数据库表。

1.2持久化

数据持久化

  • 持久化就是将程序的数据在持久化状态和瞬时状态转化的过程
  • 内存:断电及失
  • 数据库(JDBC),io文件持久化
  • 生活:冷藏,罐头

为什么需要持久化?

  • 有一些对象,不能让他丢掉
  • 内存太贵了
1.3持久层

Dao层,Service层,Controller层…

  • 完成持久化工作的代码块
  • 层界限十分明显

2.为什么使用MyBatis

  • JDBC:
    • SQL编写在代码中,耦合度比较高
    • 实际开发中SQL会经常被更新,维护不易
  • HiBernate 和 JPA
    • 内部自动生成SQL,不方便特殊优化
    • 长难复杂的SQL,对HiBernate来说处理很不如意
    • 基于全映射的全自动框架,进行字段部分处理不叫困难,并且会导致数据库性能下降
  • MyBatis
    • SQL和Java编码分离,功能划分清楚,一个专注数据,一个专注业务
    • 核心SQL可以自己编写,优化比较方便

3.MyBatis 的使用

3.1Mybatis环境搭建

步骤:

​ 1.创建Maven工程,并导入相关依赖

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wdzl</groupId>
    <artifactId>HelloMyBatis</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <!-- 测试单元 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- Myssql连接驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!-- 日志解析lo4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>


</project>

​ 2.创建实体类

在这里插入图片描述

提供get set方法 和 构造方法

​ 3.创建dao层接口:UserDao

在这里插入图片描述

​ 4.创建MyBatis主配置文件:SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务的类型 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="13992794421"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"></mapper>
    </mappers>
</configuration>

​ 5.创建映射配置文件:UserDao.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">
<mapper namespace="com.wdzl.dao.UserDao"><!-- 对应dao层的全限定类名-->
    <select id="findAll" resultType="com.wdzl.pojo.Student">
        select*from student;
    </select>
</mapper>
注意事项:

​ 1.创建directory 和 package的区别

​ directory:com.wdzl.dao 创建的是一级目录

​ package:com.wdzl.dao创建了三级目录

​ 2.MyBatis的映射配置文件所在目录层级要与对应的dao层接口目录层级相同

​ 3.映射配置文件mapper标签namespace属性的值必须对应接口的全限定类名。

​ 4.映射配置文件select标签id属性必须与对应接口中的方法名一致,不能随便写。

​ 5.只要遵循2,3,4的规定,我们就不用去写接口的实现类

3.2测试案列

步骤:

  1. 读取配置文件
  2. 创建SqlSessionFactory对象 —> 通过SqlSessionFactoryBuilder对象获取
  3. 使用工厂对象生产SqlSession对象
  4. 使用SqlSession对象获取接口的代理对象
  5. 使用代理对象调用方法
  6. 释放资源

在这里插入图片描述

在这里插入图片描述

3.3 MyBatis 注解入门

1.我们先新建一个Maven工程,将上一个工程的内容都复制到该工程中。

在这里插入图片描述

2.因为该案例使用的是注解方式,所以 映射配置文件就不需要了我们可以将它删除掉,并在相应的接 口方法上写上注解即可。

在这里插入图片描述

3.修改sqlMapConfig.xml

在这里插入图片描述

4.MyBatis- CRUD操作

4.1添加

需求:向User表中添加一名用户,数据自拟

1.在UserDao中添加方法

在这里插入图片描述

2.在UserDao.xml中配置该方法

在这里插入图片描述

注意:取值这里有两种方式#{} 和 ${}

  • #{} : 采取预编译方式

  • ${}:采取字符串拼接

可以通过控制台日志查看

3.编写测试类

我们将前4步提 取出来放在 init() 方法中,释放资源提取到 destory() 方法中

public class UserDaoTest {
    private InputStream inputStream;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private UserDao userDao;






    @Before
    public void init() throws IOException {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(inputStream);
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After
    public void destory() throws IOException {
        inputStream.close();
        sqlSession.close();
    }

    @Test
    public void findAllTest(){
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }

    }

    @Test
    public void addUserTest(){
        User user = new User(0,"屈波","2000-02-18","男","安康");
        userDao.addUser(user);

        sqlSession.commit();
        System.out.println(user);
    }
}

4.2修改

需求:将用户名为刘德华的地址改为宝鸡

1.在 UserDao 接口中添加相应的方法

    /**
     * 修改用户地址
     */
    void updateUser(User user);

2.在UserDao.xml中进行配置

 <!-- 修改数据-->
    <update id="updateUser" parameterType="com.wdzl.pojo.User">
        update mybatis.user set address=#{address} where username=#{username};
    </update>

3.测试

 @Test
    public void updateUserTest(){
        User user = new User();
        user.setUsername("刘德华");
        user.setAddress("宝鸡");
        userDao.updateUser(user);

        sqlSession.commit();

    }

4.3删除

需求:根据username删除用户

  1. 在 UserDao 接口中添加相应的方法
    /**
     * 删除用户信息
     */
    void delUser(User user);
  1. 在UserDao.xml中进行配置
 <!-- 删除数据-->
    <delete id="delUser" parameterType="com.wdzl.pojo.User">
        delete from user where username=#{username};
    </delete>
  1. 测试
    @Test
    public void delUserTest(){
        User user = new User();
        user.setUsername("赵童");
        userDao.delUser(user);


        List<User> users = userDao.findAll();
        for(User user3 : users){
            System.out.println(user3);
        }
        sqlSession.commit();
    }

4.4 查询一条数据

需求:根据用户id查询 用户信息

1.在 UserDao 接口中添加相应的方法

    /**
     *根据id查询指定用户信息
     */
    User findUserById(int id);

2.在UserDao.xml中进行配置

    <!-- 根据id查找用户信息-->
    <select id="findUserById" parameterType="INT" resultType="com.wdzl.pojo.User">
        select *from user where id=#{id};
    </select>

3.测试

    @Test
    public void findUserByIdTest(){
        User userById = userDao.findUserById(2);
        System.out.println(userById);
    }

4.5 根据名称模糊查询用户

需求:根据用户name模糊查询 用户信息

1.在 UserDao 接口中添加相应的方法

 /**
     * 模糊查询-根据用户名模糊查询用户信息
     */
    List<User> findUserByName(String name);

2.在UserDao.xml中进行配置

 <!-- 模糊查询-->
    <select id="findUserByName" parameterType="String" resultType="com.wdzl.pojo.User">
        select * from user where username like #{name};
    </select>

3.测试

    @Test
    public void findUserByNameTest(){

        List<User> users = userDao.findUserByName("%力%");
        for (User user : users){
            System.out.println(user);
        }
    }

4.5 使用聚合函数

需求:使用聚合函数查询总记录数

1.在 UserDao 接口中添加相应的方法

    /**
     * 查询总记录数
     */
    int findTotal();

2.在UserDao.xml中进行配置

    <!-- 查询总记录数-->
    <select id="findTotal" resultType="INT">
        select count(id) from user;
    </select>

3.测试

    @Test
    public void findTotalTest(){
        int total = userDao.findTotal();
        System.out.println(total);
    }

4.6 插入数据,获取当前保存数据的自增长ID

该需求需要一条sql语句:

SELECT LAST_INSERT_ID();

1.在配置文件中,找到添加用户的配置标签,在该标签内使用 获取当前插入数据的自增 长ID

    <!--添加用户-->
    <insert id="addUser" parameterType="com.wdzl.pojo.User">
    <selectKey keyProperty="id" order="AFTER" resultType="int">
        select last_insert_id();
    </selectKey>
        insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address});
    </insert>

keyProperty: 对应的实体类属性名

keyColumn:对应数据库列名

Order : 执行的顺序,after-在插入操作后执行

2.测试

/**
* 测试添加功能-获取当前添加用户的自增id
*/
@Test
public void testAdd2() throws IOException {
//创建用户
User user = new User(0,"刘德华",new Date(),"男","中国香港");
//保存之前
System.out.println(user);
//1.执行操作
userDao.addUser(user);
//2. 提交事务
session.commit();
//保存之后
System.out.println(user);
}

保存之后的user对象的id就会变成当前数据库中实际的id

5. 参数详解

9.1 parameterType 输入类型

  1. 传递基本数据类型和 String
  2. 传递pojo对象

​ 当传递参数为对象时,在sql语句中获取对象属性值需要使用OGNL表达式

  • OGNL:Object Graphic Navigation Language 对象图导航语言
  • 它是通过对象的取值方式来获取值,在写法上把get给省略了
    • 在类中,我们获取值:user.getUsername();
    • 在OGNL中:user.userName
  • Mybatis中为什么能直接写userName,而不加 user. 呢?
    • 因为在 parameterType 中已经提供了属性所属的类,所以可以省略类名

9.2 使用包装类型作为参数类型

有时候我们的查询条件可能是符合条件,比如说查询条件需要用户信息,还需要其他信息,这些信 息可以组成一个对象,这时候我们就可以考虑使用包装类来组合条件。

  1. 创建包装类QueryVo
/**
 * 传递参数的包装类
 */
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public QueryVo() {
    }

    public QueryVo(User user) {
        this.user = user;
    }
}

  1. 在接口中定义相应方法
    /**
     * 根据QuerytVo查询用户信息
     */
    List<User> findUserByVo(QueryVo vo);
  1. 在配置文件UserDao.xml中进行配置
 <!-- 根据包装类模糊查询用户信息-->
    <select id="findUserByVo" parameterType="com.wdzl.pojo.QueryVo" resultType="com.wdzl.pojo.User">
        select * from user where username like #{user.username}
    </select>

4.测试

    @Test
    public void findByVoTest(){
        QueryVo queryVo = new QueryVo();
        User user = new User();
        user.setUsername("%力%");
        queryVo.setUser(user);
        List<User> userByVo = userDao.findUserByVo(queryVo);
        for (User user2 : userByVo){
            System.out.println(user2);
        }
    }

9.3 实体类属性与表字段不对应的问题解决

​ 首先我们先将 User 类中的 id 属性名改为 uid ,重写类中的方法,重新执行查询功能,我们会发现,查出来的数据,id项都为空,这是因为属性和数据库字段名无法匹配的原因,对于这些问题,我们有3种解决方案。

方案1:统一实体类和表字段的名称

方案2:给数据库字段加别名 ,让别名与实体类属性名 统一(查询效率比较高)

我们以 根据包装类信息模糊查询用户信息为例,对sql语句进行修改,并给不对应的列起一个别名。

<!--根据包装类信息模糊查询用户数据-->
<select id="findUserByVo" parameterType="com.wdzl.domain.QueryVo"
resultType="com.wdzl.domain.User">
	select id as uid,username,birthday,sex,address from user where
username like #{user.username};
</select>

方案3:在UserDao.xml中配置对应关系

1.在配置文件UserDao.xml中添加映射配置信息

<resultMap id="userMap" type="com.wdzl.pojo.User">
        <id property="uid" column="id"></id>
        <result property="username" column="username"></result>
    </resultMap>
    <!--查询所有用户信息的方法-->
    <select id="findAll" resultMap="userMap">
       select * from user;
    </select>

6. MyBatis实现Dao层的开发

​ 现实开发中,有时候也是需要我们自己去实现Dao层接口,那么如何使用MyBatis框架自定义实现类是我们接下来要研究的内容。

1.添加UserDao对应的实现类

package com.wdzl.dao.impl;

import com.wdzl.dao.UserDao;
import com.wdzl.pojo.QueryVo;
import com.wdzl.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory factory;
    private SqlSession sqlSession;

    public UserDaoImpl() {
    }



    public UserDaoImpl(SqlSessionFactory factory){
        this.factory=factory;
        sqlSession = factory.openSession();
    }
    @Override
    public List<User> findAll() {

        //2.调用sqlSession方法
        List<User> users = sqlSession.selectList("com.wdzl.dao.UserDao.findAll");
        return users;
    }

    @Override
    public void addUser(User user) {

        //2.调用方法
        sqlSession.insert("com.wdzl.dao.UserDao.addUser", user);
        //3.提交事务
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();
    }

    @Override
    public void updateUser(User user) {
        sqlSession.update("com.wdzl.dao.UserDao.updateUser",user);
        //3.提交事务
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();

    }

    @Override
    public void delUser(User user) {
        sqlSession.delete("com.wdzl.dao.UserDao.delUser",user);
        sqlSession.commit();
        sqlSession.close();

    }

    @Override
    public User findUserById(int id) {
        User user = sqlSession.selectOne("com.wdzl.dao.UserDao.findUserById", id);
        return user;
    }

    @Override
    public List<User> findUserByName(String name) {
        List<User> list = sqlSession.selectList("com.wdzl.dao.UserDao.findUserByName", name);
        return list;
    }

    @Override
    public int findTotal() {
        Integer integert = sqlSession.selectOne("com.wdzl.dao.UserDao.findTotal");
        return integert;
    }

   
}

测试:

public class UserDaoTest {
    private InputStream inputStream;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    private UserDao userDao;






    @Before
    public void init() throws IOException {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(inputStream);
        userDao = new UserDaoImpl(factory);

    }

    @After
    public void close() throws IOException {
        inputStream.close();

    }

    @Test
    public void findAllTest(){
        UserDao userDao = new UserDaoImpl(factory);
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }

    }
    @Test
    public void addUserTest(){
        User user = new User(0,"王必武","2000-5-6","男","湖南");
        userDao.addUser(user);

    }

    @Test
    public void updateUserTest(){
        User user = new User();
        user.setUsername("唐康");
        user.setAddress("宝鸡");

        userDao.updateUser(user);

    }

    @Test
    public void delUserTest(){
        User user = new User();
        user.setUsername("唐康");

        userDao.delUser(user);

    }

    @Test
    public void findUserByIdTest(){

        User user = userDao.findUserById(20);

        System.out.println(user);;

    }

    @Test
    public void findUserByNameTest(){

        List<User> users = userDao.findUserByName("%波");

       for (User user : users){
           System.out.println(user);
       }

    }

    @Test
    public void findTotalTest(){

        int total = userDao.findTotal();
        System.out.println(total);
    }




}

7.标签

7.1 properties标签

**方式一:**将配置提取出来进行统一管理,在需要使用的地方使用 ${}引用即可

1.提取

在这里插入图片描述

2.引用

在这里插入图片描述

方式二:引用外部配置文件

在这里插入图片描述

引用外部有两个属性:

  • resource : 用于指定配置文件的位置类路径的写法,并且必须存在于类路径下。

  • url : 统一资源定位符。可以标识资源的位置

Http : // localhost : 8080 /book/index.jsp

​ 协议 主机地址 端口 URI

7.2 typeAliases标签 和 package标签

在主配置文件中使用 typeAliases 配置别名,它只能给实体类配置别名。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1bQD8L3M-1616665998027)(D:\图片\1.1.1.1.png)]

在 typeAliases 中有两个属性

**type:**用来指定起别名的实体类,如果省略 alias 属性,则使用默认别名,默认别名为类名 ,不区分大小写,任意组合都可识别。

**alias:**指定一个新的别名,比如上图案例中将别名设置为 hehe ,则在下面使用时使用 hehe 即可表 示User类。新的别名也不区分大小写。

当实体类比较多时,我们可以使用 package 标签批量给包中的类添加别名

8.动态SQL

8.1 if标签

**需求:**根据给定条件完成对满足条件的用户信息复合查询:查询满足名称叫刘德华 且 性别为男的所有 员工信息

<!--根据给定条件 完成复合查询-->
<select id="findUserByConditions" parameterType="user" resultType="User">
select * from user where 1=1
<if test="username !=null">
and username=#{username}
</if>
</select>

8.2 where标签

where标签是为了解决拼接sql时需要添加一个恒等式的问题

<!--根据给定条件 完成复合查询-->
<select id="findUserByConditions" parameterType="user" resultType="user">
select * from user
<where>
<if test="username !=null and username!=''">
and username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</where>
</select>

8.3 foreach 标签

当我们要查询满足条件在某个范围中的信息时:

SQL:

select * from user where id in (1,3,5,7,9);

1.UserDao 添加相应方法并在映射文件中进行配置

/**
     * 根据给定条件对满足条件的用户信息进行复合查询
     * 查询满足条件为刘德华,性别为男的所有用户信息
     */
    List<User> findUserByConditions(User user);
    
    List<User> findUserByIds(QueryVo vo);

 <select id="findUserByConditions" parameterType="user" resultType="user">
        select * from user
        <where>
        <if test="username != null">
            and username = #{username}
        </if>
        <if test="sex != null">
            and sex = #{sex}
        </if>
        <if test="address != null">
            and address = #{address}
        </if>
        </where>
    </select>

    <select id="findUserByIds" parameterType="queryvo" resultType="user">
        select * from user
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>


</mapper>

collection:遍历的集合

**open:**拼接SQL以该属性值为开头

**close:**拼接SQL以该属性值为结尾

item:变量名,相当于增强for循环中的那个变量。拼接在 open 和 close 之间

**separator:**元素(变量)间以什么分割

#{变量名}:必须与 item 属性保持一致。

9.MyBatis 的 多表查询

在MySQL中 表与表之间的关系

  • 一对一
  • 一对多(多对一)
  • 多对多

举例:

  • 一对一
    • 人 和 身份证,一个人对应一个身份证,一个身份证对应一个人
  • 一对多(多对一):
    • 班级和学生,一个班级对应多个学生,一个学生只能对应一个班级。这种关系就是一对多(多对 一)的关系。
  • 多对多
    • 学生和老师:一个学生可以有多个老师,一个老师可以有多个学生
  • 特殊
    • 如果将订单取出,这个订单只能属于一个用户, 所以,在MyBatis中, 就把多对一的关系按照一对一的情况进行处理。

9.1MyBatis中的多表查询 -1多对一,一对多

准备工作:Module创建 并能实现单表信息查询

1.数据库表:用户表 和 账户表

CREATE DATABASE mybatis2 CHARSET utf8;
USE mybatis2;
CREATE TABLE `user` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NOT NULL COMMENT '用户名称',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`username`,`birthday`,`sex`,`address`)
VALUES
(NULL,'老王','2017-05-27 18:27:09','男','北京'),
(NULL,'小王','2019-04-03 15:09:37','女','西安'),
(NULL,'小李','2019-07-22 17:44:33','女','咸阳'),
(NULL,'小刘','2018-03-04 15:52:36','男','渭南'),
(NULL,'大王','2016-11-03 17:37:26','男','富平'),
(NULL,'小马','2016-04-09 01:24:40','女','上海');
CREATE TABLE `account` (
`ID` INT(11) NOT NULL COMMENT '编号',
`UID` INT(11) DEFAULT NULL COMMENT '用户编号',
`MONEY` DOUBLE DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `account`(`ID`,`UID`,`MONEY`) VALUES (1,2,1000),(2,1,1000),
(3,2,2000);

2.创建主配置文件:SqlMapConfig.xml,并且将log4j,jdbc的配置文件一起复制到 resources 目录下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
   <!--  读取外部配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!-- 配置别名-->
    <typeAliases>
        <package name="com.wdzl.pojo"/>
<!--        <typeAlias type="com.wdzl.pojo.User" alias="user"></typeAlias>-->
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <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="com/wdzl/dao/UserDao.xml"/>

        <mapper resource="com/wdzl/dao/AccountDao.xml"/>
    </mappers>

</configuration>

3.建立两个实体类:用户实体类 和 账户实体类

User:

/**
 * 用户实体类
 */
public class User {
    private int uid;
    private String username;
    private Date birthday;
    private char sex;
    private String address;
    //一用户可以有多个账户
    private List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public User(int uid, String username, Date birthday, char sex, String address) {
        this.uid = uid;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public User() {
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex=" + sex +
                ", address='" + address + '\'' +
                ", accounts=" + accounts +
                '}';
    }
}

Account:

/**
 * 账户表对应实体类
 */
public class Account {
    private int aid;
    private int uid;
    private Double money;
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Account(int aid, int uid, Double money) {
        this.aid = aid;
        this.uid = uid;
        this.money = money;
    }

    public Account() {
    }

    @Override
    public String toString() {
        return "Account{" +
                "aid=" + aid +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }

    public int getAid() {
        return aid;
    }

    public void setAid(int aid) {
        this.aid = aid;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }
}

4.创建各自实体类操作的接口

UserDao

/**
* 操作用户的接口
* @author lp
* @version 1.0
*/
public interface UserDao {
/**
* 查询所有用户信息
*/
List<User> findAll();
}

AccountDao

/**
* 操作账户的接口
*/
public interface AccountDao {
/**
* 查询所有账户信息
*/
List<Account> findAll();
}

5.创建各接口对应的映射配置文件

UserDao.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">
<mapper namespace="com.wdzl.dao.UserDao">
    <resultMap id="userAccountMap" type="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>

        <collection property="accounts" ofType="com.wdzl.pojo.Account" column="uid">
            <id property="aid" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>
    </resultMap>
    <!-- 查询用户列表-->
    <select id="findAll" resultMap="userAccountMap">
        SELECT * FROM USER u LEFT OUTER JOIN account a ON u.uid = a.uid;
    </select>

</mapper>

AccountDao.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">
<mapper namespace="com.wdzl.dao.AccountDao">
    <!-- 定义封装account 和 user 的 resultMap-->
    <resultMap id="accountUserMap" type="account">
        <id property="aid" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 配置一对一的关系映射:配置user的内容-->
        <association property="user" column="uid" javaType="com.wdzl.pojo.User">
            <id property="uid" column="uid"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
    <!-- 查询账户表信息-->
    <select id="findAll" resultMap="accountUserMap">
        SELECT a.aid,a.money,u.uid,u.username,u.sex,u.address FROM account a , USER u WHERE a.uid = u.uid
    </select>

</mapper>

6.将映射配置文件添加到主配置文件中

<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
<mapper resource="com/wdzl/dao/AccountDao.xml"/>
</mappers>

7.测试:分别测试UserDao 和 AccountDao

/**
* UserDao测试类
* @author lp
* @version 1.0
*/
public class UserTest {
private InputStream is;
private SqlSessionFactoryBuilder builder;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
/**
* 初始化方法
* @throws IOException
*/
@Before
public void init()throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
/*
使用SqlSessionFactoryBuilder创建工厂的好处是MyBatis将如何读取配置文件,如何使用
配置文件,如何封装等细节都进行了封装,使我们使用极简的方式来实现功能。
*/
builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.使用工厂生产SqlSession对象
session = factory.openSession(true);
//4.使用SqlSession创建Dao接口的代理对象
userDao = session.getMapper(UserDao.class);
}
/**
* 释放资源* @throws IOException
*/
@After
public void destroy() throws IOException {
//6.释放资源
session.close();
is.close();
}
/**
* 查询用户
*/
@Test
public void testFindAllUser() {
List<User> all = userDao.findAll();
for (User user : all) {
System.out.println(user);
}
}
}
/**
* 测试类
* @author lp
* @version 1.0
*/
public class AccountTest {
private InputStream is;
private SqlSessionFactoryBuilder builder;
private SqlSessionFactory factory;
private SqlSession session;
private AccountDao accountDao;
/**
* 初始化方法
* @throws IOException
*/
@Before
public void init()throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
/*
使用SqlSessionFactoryBuilder创建工厂的好处是MyBatis将如何读取配置文件,如何使用
配置文件,如何封装等细节都进行了封装,使我们使用极简的方式来实现功能。
*/
builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.使用工厂生产SqlSession对象
session = factory.openSession(true);
//4.使用SqlSession创建Dao接口的代理对象
accountDao = session.getMapper(AccountDao.class);
}
/**
* 释放资源需求:查询所有账户信息的同时,也显示账户所属用户的信息(多对一)
1.首先确定SQL语句
改进
2. 在实体类中添加一对一关系
在 Account 类中添加成员变量 user ,并提供 get/set 方法
* @throws IOException
*/
@After
public void destroy() throws IOException {
//6.释放资源
session.close();
is.close();
}
/**
* 查询账户
*/
@Test
public void testFindAllUser() {
List<Account> all = accountDao.findAll();
for (Account account : all) {
System.out.println(account);
}
}
}

9.2MyBatis中的多表查询-2 多对多

我们知道SQL中 多对多的关系需要借助一张中间。

需求:查询角色信息的同时显示赋予该角色的用户信息

步骤:

  1. 建立两张表,用户表 和 角色表
    • 让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含这两张表的主键,并且这两个主键在中间表中是外键
  2. 建立两个实体类:用户实体类 和 角色实体类
    • 让用户和角色实体类能体现出多对多的关系:各自包含对方的一个集合引用
  3. 建立配置文件
    • 用户配置文件
    • 角色配置文件
  4. 实现配置
    • 查询用户时,可以同时得到该用户所包含的角色信息。
    • 当我们查询角色时,可以同时得到拥有该角色的用户信息。

实现:先实现单表查询,再实现多对多关系查询

1.新建Module, 修改pom.xml,添加相应依赖

2.将多表查询1的Module中 src下的内容拷贝到当前Module中

3.将 Account有关的类,接口 ,配置文件等进行删除

  • 实体类
  • 接口
  • AccountDao配置文件
  • User实体类中与Account有关的属性和方法
  • UserDao.xml中有关Account的配置信息
  • 测试类:Account测试类 和 User测试类中有关Account的部分

4.创建数据库表并插入数据

CREATE TABLE `role` (
`rid` INT(11) NOT NULL COMMENT '编号',
`ROLE_NAME` VARCHAR(30) DEFAULT NULL COMMENT '角色名称',
`ROLE_DESC` VARCHAR(60) DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`rid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `role`(`rid`,`ROLE_NAME`,`ROLE_DESC`) VALUES (1,'院长','管理整个学
院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
CREATE TABLE `user_role` (
`UID` INT(11) NOT NULL COMMENT '用户编号',
`RID` INT(11) NOT NULL COMMENT '角色编号',
PRIMARY KEY (`UID`,`RID`),
KEY `FK_Reference_10` (`RID`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`rid`),
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`uid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user_role`(`UID`,`RID`) VALUES (1,1),(3,1),(1,2);

5.创建实体类

public class Role {
    private int rid;
    private String role_name;
    private String role_desc;
    private List<User> users;

    public Role(int rid, String role_name, String role_desc) {
        this.rid = rid;
        this.role_name = role_name;
        this.role_desc = role_desc;
    }

    public Role() {
    }

    public int getRid() {
        return rid;
    }

    public void setRid(int rid) {
        this.rid = rid;
    }

    public String getRole_name() {
        return role_name;
    }

    public void setRole_name(String role_name) {
        this.role_name = role_name;
    }

    public String getRole_desc() {
        return role_desc;
    }

    public void setRole_desc(String role_desc) {
        this.role_desc = role_desc;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    @Override
    public String toString() {
        return "Role{" +
                "rid=" + rid +
                ", role_name='" + role_name + '\'' +
                ", role_desc='" + role_desc + '\'' +
                ", users=" + users +
                '}';
    }
}
public class User {
    private int uid;
    private String username;
    private Date birthday;
    private char sex;
    private String address;
    private List<Role> roles;

    public User(int uid, String username, Date birthday, char sex, String address) {
        this.uid = uid;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public User() {
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex=" + sex +
                ", address='" + address + '\'' +
                ", roles=" + roles +
                '}';
    }
}

public class UserRole {
    private int uid;
    private int rid;

    public UserRole(int uid, int rid) {
        this.uid = uid;
        this.rid = rid;
    }

    public UserRole() {
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public int getRid() {
        return rid;
    }

    public void setRid(int rid) {
        this.rid = rid;
    }

    @Override
    public String toString() {
        return "UserRole{" +
                "uid=" + uid +
                ", rid=" + rid +
                '}';
    }
}

6.创建Dao接口

public interface RoleDao {
    /**
     * 查询角色列表
     * @return
     */
    List<Role> findAll();
}



public interface UserDao {


    List<User> findAll();
}

7.创建映射配置文件

RoleDao.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">
<mapper namespace="com.wdzl.dao.RoleDao">
    <!-- 定义封装account 和 user 的 resultMap-->
    <resultMap id="roleMap" type="com.wdzl.pojo.Role">
        <id property="rid" column="rid"></id>
        <result property="role_name" column="ROLE_NAME"></result>
        <result property="role_desc" column="ROLE_DESC"></result>

        <collection property="users" ofType="com.wdzl.pojo.User" column="uid">
            <id property="uid" column="uid"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </collection>

    </resultMap>
    <select id="findAll" resultMap="roleMap">
        SELECT r.*,u.* FROM role r
         LEFT OUTER JOIN user_role ur ON r.`rid`=ur.`RID`
         LEFT OUTER JOIN USER u ON u.`uid`=ur.`UID`
    </select>


</mapper>

UserDao.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">
<mapper namespace="com.wdzl.dao.UserDao">
    <resultMap id="userMap" type="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <collection property="roles" ofType="com.wdzl.pojo.Role" column="rid">
            <id property="rid" column="rid"></id>
            <result property="role_name" column="ROLE_NAME"></result>
            <result property="role_desc" column="ROLE_DESC"></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="userMap">
        SELECT u.*,r.* FROM USER u
         LEFT OUTER JOIN user_role ur ON u.`uid`=ur.`UID`
         LEFT OUTER JOIN role r ON r.`rid`=ur.`RID`
    </select>


</mapper>

8.主配置文件中添加相应的映射文件配置

   <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"/>

        <mapper resource="com/wdzl/dao/RoleDao.xml"/>
    </mappers>

9.测试

public class RoleDaoTest {
    private InputStream resourceAsStream;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private RoleDao roleDao;


    @Before
    public void init() throws IOException {
         resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
         factory = builder.build(resourceAsStream);
         sqlSession = factory.openSession();
         roleDao = sqlSession.getMapper(RoleDao.class);
    }

    @After
    public void destroy() throws IOException {
        resourceAsStream.close();
        sqlSession.close();
    }

    @Test
    public void findAllTest(){
        List<Role> roles = roleDao.findAll();
        for (Role role : roles){
            System.out.println(role);
        }
    }
}

/**
 * 用户表的测试
 */
public class UserDaoTest {
    private InputStream resourceAsStream;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private UserDao userDao;


    @Before
    public void init() throws IOException {
         resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
         factory = builder.build(resourceAsStream);
         sqlSession = factory.openSession();
         userDao = sqlSession.getMapper(UserDao.class);
    }

    @After
    public void destroy() throws IOException {
        resourceAsStream.close();
        sqlSession.close();
    }

    @Test
    public void findAllTest(){
        List<User> users = userDao.findAll();
        for (User user : users){
            System.out.println(user);
        }

    }
}

10.延迟加载

首先我们先来分析一个问题:

问题:

  • 在一对多的关系中,我们有一个用户,他有1000个账户。
  • 在查询用户时,要不要把关联的账户查出来?
  • 在查询账户时,要不要把关联的用户查出来?

图解:

  • 问题1:如果查出来,这一千个账户就会对应一千个账户对象,但是这些对象对于我们查询用户信 息,无疑是没有用的,这样就造成了资源的浪费

在这里插入图片描述

所以:用户下的账户信息应该是什么时候使用,什么时候查询

  • 问题2:我们查询账户信息时需要知道对应的用户信息

在这里插入图片描述

所以:账户所属用户信息应该随着账户的查询一并查出来

针对上述两个问题,我们引出两个概念:延迟加载和立即加载

延迟加载:在真正使用的时候才发起查询,不用的时候不查询。延迟加载也可以称为按需加载或 懒加 载。

立即加载:无论数据是否使用,只要调用方法,就会立马执行查询

在多表关系中:

一对多,多对多:通常情况下我们对 “多” 的一方采用延迟加载

多对一,一对一:通常情况下我们对 “一” 的一方采用立即加载

11.缓存

概述:

​ 存在于内存中的数据叫做缓存

应用:

​ 减少和数据库的交互,提高执行效率

适用:

  • 经常查询并且不经常改变的。

  • 数据的正确与否对最终结果影响不大的。(比如视频访问量,回帖数量等)

不适用:

  • 经常改变的数据

  • 数据的正确与否对最终结果影响很大时(银行汇率,股票价格)

分类

​ MyBatis中分为 一级缓存 和 二级缓存

11.1 一级缓存

概述

​ 它指的是MyBatis中SqlSession对象的缓存。当我们执行查询后,查询结果会存入到SqlSession为我 们提供的一款存储区域中。该区域的存储结构为Map。当我们再次查询同样数据时,MyBatis首先去一 级缓存中查询,如果存在,则直接拿取使用

注意:

​ 当SqlSession对象消失时,MyBatis的一级缓存也会消失

注意:

​ 当sqlSession调用 add , update , delete,commit , close方法时,MyBatis会自动清空一级缓存,防止缓存数据与数据库中的数据不一致。

11.2 二级缓存

概述

​ 它指的是MyBatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的 SqlSession对象共享二级缓存。

12. MyBatis的注解开发

注意:

​ 注解开发是为了简化映射配置文件,但是主配置文件还是存在。

环境搭建 :

  1. 新建Module

  2. 修改pom.xml,添加相应的依赖

  3. 创建实体类User

  4. 创建主配置文件:SqlSessionConfig.xml

    • 引入外部配置文件
    • 配置别名
    • 配置数据源
    • 指定带有注解的dao层接口所在位
  5. 创建UserDao

    • 声明findAll()方法
    • 在该方法上使用注解@Select
  6. 测试

  • 读取配置文件
  • 获取SqlSessionFactory对象
  • 使用Factory生成SqlSession
  • 使用SqlSession生成代理对象
  • 调用方法
  • 释放资源
  1. 注意事项:

    采用注解开发时,如果对应目录下还存在配置文件,及时在主配置文件中没有配置 xml ,运行时也会报错。

  • 删除配置文件

  • 将配置文件移动到其他目录下

注解分类:

MyBatis针对CRUD操作一共有四个注解

  • @Select
  • @Insert
  • @Delete
  • @Update

12.1注解方式-CRUD操作

UserDao

public interface UserDao {

    @Select("select * from user")
    List<User> findAll();


    //方法存在多个参数,所有的参数前面加上@Param()注解
    @Select("select * from user where uid=#{id}")
    User findUserById(@Param("id") int id);


    @Insert("insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})")
    void addUser(User user);

    @Update("update user set address=#{address} where uid=#{uid}")
    void updateUser(User user);

    @Delete("delete from user where uid=#{id}")
    void delUser(@Param("id") int id);

}

测试

/**
 * 用户表的测试
 */
public class UserDaoTest {
    private InputStream resourceAsStream;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private UserDao userDao;


    @Before
    public void init() throws IOException {
         resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
         factory = builder.build(resourceAsStream);
         sqlSession = factory.openSession();
         userDao = sqlSession.getMapper(UserDao.class);
    }

    @After
    public void destroy() throws IOException {

        resourceAsStream.close();
        sqlSession.close();
    }

    @Test
    public void findAllTest(){
        List<User> users = userDao.findAll();
        for (User user : users){
            System.out.println(user);

        }
    }

    @Test
    public void findUserTest(){
        User userById = userDao.findUserById(1);
        System.out.println(userById);
    }

    @Test
    public void addUserTest(){
        Date date =new Date();
        char s = '男';
        userDao.addUser(new User(0,"你好",date,s,"中国"));
        sqlSession.commit();

    }

    @Test
    public void updateUserTest(){
        User user = new User();
        user.setUid(7);
        user.setAddress("西安");
        userDao.updateUser(user);
        sqlSession.commit();

    }

    @Test
    public void delUserTest(){
      userDao.delUser(7);
        sqlSession.commit();

    }


}

12.2 注解方式-其他操作

/**
* 根据id查询用户
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findUserById(Integer id);

/**
* 根据用户名模糊查询用户信息
* @param name
* @return
*/
@Select("select * from user where username like #{username}")
List<User> findUserByName(String name);
@Select("select count(*) from user")
int findTotal();

12.3 处理字段名与属性名不同问题

通过 @Results@Rusult 来处理不同问题

在这里插入图片描述

13.连接池

13.1 概述

​ 连接池就是用于存储连接对象的一个容器,当系统初始化完成后,容器被创建,容器会申请一些连 接对象,当用户访问数据库时,从容器中获取连接对象即可。访问完之后,会将连接对象归还给连接 池。这样做可以提高效率,提高连接对象的复用,不必频繁的创建和释放连接对象。

13.2 MyBatis连接池

连接池有很多种,最为熟悉的比如c3p0,DBCP,druid等。

MyBatis支持三种内置的数据源类型:

  • POOLED: 实现dataSource接口,并且使用了池的思想。
  • UNPOOLED: 同样也是实现了dataSource接口,但是该类型并没有使用池的思想。
  • JDNI: 采用服务器提供的JDNI技术实现的,并且在不同服务器之间获取的连接池是不一样的。
    • 当前框架教学使用的是Tomcat服务器,采用的是dbcp连接池技术
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于MyBatis框架的学习 的相关文章

随机推荐

  • 什么是范数(Norm),其具有哪些性质

    文章目录 直观的感受一下范数范数的定义直观的感受下范数的边界图像范数的性质参考资料 直观的感受一下范数 先直观的感受一下二维空间的范数 xff0c 假设在二维空间的向量为 v 61 x y
  • Hugging Face快速入门(重点讲解模型(Transformers)和数据集部分(Datasets))

    文章目录 本文内容HuggingFace简介Hugging Face模型讲解Transforms简介Transformers安装使用Transformers进行推理查找Hugging Face模型使用Hugging Face模型迁移学习 H
  • Eslint 规则说明

    1 34 no alert 34 0 禁止使用alert confirm prompt 2 34 no array constructor 34 2 禁止使用数组构造器 3 34 no bitwise 34 0 禁止使用按位运算符 4 34
  • eclipse无线循环输出时,怎样关闭

    eclipse控制台无限循环输出的时候找到 xff0c 找到控制台右边有一个红色方块按钮 xff0c 点击即可停止运行 如下图 有问题欢迎私聊或者发送邮箱 xff08 964427082 64 qq com xff09 一起讨论
  • goland中报错: Unresolved reference 错误解决

    前言 今天早上项目导入的包标红了 xff0c 而且也包了unresolved reference的错误 xff0c 但是程序却可以正常运行 xff0c 在网上找了多种方法 xff0c 最后可以了 xff0c 但是并不知道是哪一个起了作用 x
  • 关于打游戏ping值不稳定问题的解决经历(疑难篇)

    首先 xff0c 大概几天之前 xff0c 笔者发现自己的电脑在打游戏 xff08 lol xff09 的时候ping值忽高忽低 xff0c 就是突然从20跳到10000 43 xff0c 没有丝毫夸张 xff0c 就是这样吓人 xff0c
  • react、angularjs、vue原理应用场景总结

    React 如图 xff1a React的虚拟DOM的生成是可以在任何支持Javascript的环境生成的 xff0c 所以可以在NodeJS或Iojs环境生成 虚拟DOM可以直接转成String 然后插入到html文件中输出给浏览器便可
  • c++中对象和类的概念以及联系

    1 概念 xff1a 类是对一组性质相同的事物的程序描述 如果类在定义中不指定是private或者public的 xff0c 则系统默认为private的 使用struct声明的类 xff0c 如果对其成员不作private或者public
  • c++学习总结(一些零碎的小知识点)

    1 C 语言中 和 gt 区别 结构体变量用 运算符来访问结构体的成员 指向结构体的指针用 gt 来访问其指向的结构体的成员 gt 指向指针变量的运算符 举例 xff1a p gt m 表示指针 p 指向结构体变量中的成员 m xff1b
  • html学习之

    1 lt xff01 DOCTYPE gt 声明帮助浏览器正确的显示网页 xff0c 不是HTML标签 xff0c 它为浏览器提供了一项声明 xff0c 即HTML是用什么版本编写的 lt DOCTYE html gt lt html gt
  • Ubuntu下ssh服务器文件操作命令

    用java写了一个监视 web服务器的程序 需要部署到Ubuntu服务器版本的系统中 xff0c 遇到的第一个问题就是怎么把这个程序copy到服务器上去 xff33 xff33 xff28 服务器 什么是 xff33 xff33 xff28
  • 小狼毫配置

    小狼毫配置 安装下载 设置 安装完成后 xff0c 右键单击任务栏的小狼毫图标 xff0c 点击 输入法设定 xff0c 勾选输入法 xff08 推荐 朙月拼音 简化字 xff09 xff0c 点击 中 xff0c 选择皮肤后即可使用小狼毫
  • 第27章 联合网关 - Identity Server 4 中文文档(v1.0.0)

    通用架构是所谓的联合网关 在此方法中 xff0c IdentityServer充当一个或多个外部身份提供商的网关 该架构具有以下优点 您的应用程序只需要了解一个令牌服务 xff08 网关 xff09 xff0c 并且屏蔽了有关连接到外部提供
  • Asp.net core3.1 框架中 采用Serilog实现log日志记录

    本文以MVC框架为例 xff0c 实现log记录 在默认情况下 xff0c asp net core有自带的可实现将日志输出到控制台 xff0c 注意 xff0c 此时需要 xff0c 运行时 xff0c 要运行自托管模式才能调出控制台 如
  • 关于Lwip如何实现单网卡多IP设置

    记录 xff1a 关于Lwip如何实现单网卡多IP设置 https wenku baidu com view fb49542683d049649b6658fe html https blog csdn net sinat 20006769
  • 学习java的第一步

    1 走进Java 1 Java的三个平台版本 1 JavaSE J2SE JavaSE是其他两个平台版本的基础 2 JavaME J2ME 针对于移动端开发的版本 3 JavaEE J2EE 针对于web应用的开发版本 跨平台性 因为Jav
  • 面向对象的三大特点

    封装继承多态 1 封装 概念 xff1a 隐藏对象的属性和实现细节 xff0c 对外提供公共的访问方式 原则 xff1a 不需要用户访问的内容隐藏起来 优点 xff1a 1 安全性高 2 独立性高 3 复用性高 span class tok
  • 面向对象版图书管理系统

    span class token keyword package span org span class token punctuation span wdit span class token punctuation span unit0
  • 抽象类

    1 抽象类 概述 xff1a 用来描述抽象概念的类 xff0c 叫做抽象类 抽象类中的方法不一定有具体的实现 span class token keyword package span org span class token punctu
  • 对于MyBatis框架的学习

    1 MyBatis MyBatis 它是Apache的一个开源项目 iBatis 2010年这个项目由apache software foundation 迁 移到了google code xff0c 并且改名为MyBatis 2013年1