Mybatis入门教程

## Mybatis入门教程

Mybatis是一个半自动化的ORM框架,是一个优秀的DAO层解决方案。

官网API文档地址:https://mybatis.net.cn/index.html

### 一、 使用MyBatis的开发步骤

#### 1.导入mybatis依赖

通过这个maven仓库去找依赖,https://mvnrepository.com/

三个依赖:mysql、mybatis、junit

~~~xml
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.29</version>
    </dependency>
    <!-- junit测试包 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>
~~~

#### 2.编写MyBatis核心配置文件

mybatis-config.xml,官网提供的名字。

在资源文件resources目录下,创建mybatis-config.xml,写入配置信息

```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">
<!--mybatis的核心配置文件-->
<configuration>
    <typeAliases>
        <!--<typeAlias type="cn.hxzy.pojo.User" alias="User"/>-->
        <package name="cn.hxzy.pojo"/>
    </typeAliases>
    
    <!--environments 数据库环境 1、开发环境  2、测试环境  3、生产环境-->
    <environments default="dev">
        <environment id="dev">
            <!--事务管理 采用JDBC的事务管理机制-->
            <transactionManager type="JDBC" />
            <!--数据源配置信息-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/news_db"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments> 
    <!--映射器-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>
```

#### 3.创建实体类-POJO、创建Dao层,编写接口文件

实体类

~~~java
package cn.hxzy.pojo;

public class User {
    private Integer userId;
    private String userName;
    private String userPwd;
    private Integer userGender;

    public User() {
    }

    public User(Integer userId, String userName, String userPwd, Integer userGender) {
        this.userId = userId;
        this.userName = userName;
        this.userPwd = userPwd;
        this.userGender = userGender;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }

    public Integer getUserGender() {
        return userGender;
    }

    public void setUserGender(Integer userGender) {
        this.userGender = userGender;
    }
}

~~~



定义接口文件的后缀名为Mapper,UserMapper.java。

~~~java
package cn.hxzy.dao;

import cn.hxzy.pojo.User;

import java.util.List;

/**
 * 用户的Mapper接口文件
 */
public interface UserMapper {
    /**
     * 查询全部用户信息
     * @return 用户集合
     */
    List<User> getUserList();
}

~~~



#### 4.编写-SQL映射文件

在resources资源目录下,创建一个专门用于mapper文件的管理目录,在mapper文件夹下,创建与接口文件保持一致的SQL映射文件

UserMapper.xml

~~~xml
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace-->
<mapper namespace="cn.hxzy.dao.UserMapper">
    <select id="getUserList" resultType="cn.hxzy.pojo.User">
        select * from user
    </select>
</mapper>
~~~

maven的强大体现在有个特性叫做依赖传递。

#### 5.代码测试

~~~java
@Test
public void getGradeById() throws IOException {
    //核心配置文件的路径
    String resource = "mybatis-config.xml";
    //读取为字节输入流对象
    InputStream is = Resources.getResourceAsStream(resource);
    //通过SqlSessionFactoryBuilder来构建SqlSessionFactory对象,依赖字节输入流【数据库的连接信息】
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    //创建SQL的会话对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //根据指定类,通过反射得到接口的实例对象
    GradeMapper gradeMapper = sqlSession.getMapper(GradeMapper.class);
    //调用实例对象的查询方法
    Grade grade = gradeMapper.getGradeById(1);
    System.out.println(grade.toString());

}
~~~



### 二、 使用lombok的步骤

#### 1.安装lombok插件

在File中找到Settings找到Pplugins,搜索Lombok,进行安装。

#### 2.下载依赖

找到maven仓库,下载依赖,添加到pom.xml文件中

~~~xml
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <scope>provided</scope>
</dependency>

~~~

#### 3.打开实体类,加入注解

~~~java
@Data //get set
@AllArgsConstructor //有参构造方法
@NoArgsConstructor //无参构造方法
@ToString   //重写toString方法

~~~

#### 4.提取MybatisUtils工具类

为了减少代码量,提高系统性能,把公共的操作封装在一起,方便代码的管理。

~~~java
public class MybatisUtils {
    static SqlSessionFactory sqlSessionFactory=null;
    static SqlSession sqlSession=null;
    static {
        String resource="mybatis-config.xml";
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //执行增删改查操作的时候得到一个SqlSession对象
   public static SqlSession openSqlSession(){
       sqlSession = sqlSessionFactory.openSession(true);
       return sqlSession;
   }

    //SqlSession关闭
   public static void closeSqlSessoin(){
       sqlSession.close();
   }
}

~~~



### 三、参数入参

- 1、适用于单个参数的情况,默认按照类型入参,默认可以不写parameterType。

- 2、多个参数入参

  ​      这种情况需要添加@Param注解,进行参数名称的标注。xml文件节点上不可以添加parameterType。

- 3、可以封装为一个实体对象进行入参

​             对象加上@Param注解后,sql语句传入参数的表示方式为:#{student.studentId}

​             如果对象不加@Param注解,sql语句传入参数的表示方式为:#{studentId}

- 4、涉及到复杂数据类型传参的时候可以使用Map入参,可以加@Param("map")注解,如果添加上去后,sql语句就必须为#{map.studentId},如果没有添加

  则可以直接使用map的键的名称入参



#{ }入参与${ }入参的区别:

1、#{ } 占位符,预编译的sql语句

2、${ },变量直接拼接到sql语句中,入参方式不安全。很容易被sql注入(利用sql语句,对系统进行攻击,破坏)

~~~sql
SELECT COUNT(1) FROM userinfo 
WHERE user_name='aa' OR 1='1' AND user_pwd='bb' OR 1='1'
账号 aa' OR 1='1 
密码 bb' OR 1='1 
~~~

3、${ } 可以进行算术运算,#{ }不可以进行算术运算



### 四、事务提交

执行增删改操作的时候,默认的自动提交是关闭的,需要进行手动提交。

方式一:

~~~java
sqlSession.commit();
~~~

方式二:

```java
public static SqlSession creatSqlSession() {
    return factory.openSession(true);
}
```



### 五、resultType与resultMap

返回类型别名设置:

~~~xml
<typeAliases>
  <typeAlias alias="Grade" type="cn.hxzy.myschool"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
~~~

或者

~~~xml
<typeAliases>
  <package name="cn.hxzy.myschool.entity"/>
</typeAliases>
~~~

每一个在包 `domain.blog` 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 `domain.blog.Author` 的别名为 `author`;若有注解,则别名为其注解值。



resultMap:返回SQL语句映射的一个Map类型的结果集

数据库的经典命名法:

Orcal与Mysql

Orcal中一般字段名全部大写,如果遇到两个单词的情况,中间用下划线隔开。

mysql中一般字段名小写,如果遇到两个单词的情况,中间用下划线隔开。

resultType与resultMap不能同时存在于同一个语句块上。



### 六、高级结果映射

#### 1. 映射方式

在实际生产环境中,对于这种多表联查,映射结果有以下几种处理办法。

1.1.做一个基于业务模块的DTO实体类,一般会把所用到的业务字段合为一个实体类进行操作

~~~java
package cn.hxzy.dto;
import java.sql.Date;
public class NewsDto {
    private Integer newsId;
    private Integer newsTypeId;
    private String newsTitle;
    private String newsInfo;
    private String newsFrom;
    private String newsContent;
    private Date createTime;
    private String newsimg;
    private String newsTypeTitle;
}
~~~

1.2.在实体类上修改字段

根据关系型数据表中,数据记录的关系,进行实体类属性的定义



#### 2. 一对一的映射

实体类

~~~java
package cn.hxzy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.sql.Date;

/*
资讯实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class News {
     private Integer newsId;
     private NewsType newsType;  //把此属性改为对象
     private String newsTitle;
     private String newsInfo;
     private String newsFrom;
     private String newsContent;
     private Date createTime;
     private String newsimg;
}

~~~

Mapper.xml

~~~xml
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 命名空间..接口的包路径-->
<mapper namespace="cn.hxzy.dao.NewsMapper">

    <!--对多表联查,自定义结果集-->
    <resultMap id="newsList" type="News">
        <id property="newsId" column="newsId" />
        <result property="newsTitle" column="newsTitle" />
        <result property="newsInfo" column="newsInfo" />
        <result property="newsFrom" column="newsFrom" />
        <result property="newsContent" column="newsContent" />
        <result property="createTime" column="createTime" />
        <result property="newsimg" column="newsimg" />
        <!-- 指代的就是一个对象-->
        <association property="newsType" javaType="NewsType">
             <id property="newsTypeId" column="newsTypeId" />
             <result property="newsTypeTitle" column="newsTypeTitle"/>
        </association>
    </resultMap>

    <select id="selectAll" resultMap="newsList" >
        SELECT * FROM news t1
           LEFT OUTER JOIN newstype t2
            ON t1.`newsTypeId`=t2.`newsTypeId`
    </select>

</mapper>
~~~

接口

~~~java
package cn.hxzy.dao;

import cn.hxzy.pojo.News;

import java.util.List;

public interface NewsMapper {
    //查询全部的资讯信息
    List<News> selectAll();
}

~~~

测试

~~~java
package cn.hxzy.dao;

import cn.hxzy.pojo.News;
import cn.hxzy.pojo.User;
import cn.hxzy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class NewsMapperTest {
    @Test
    public void selectAll() throws Exception{
        SqlSession sqlSession = MybatisUtils.creatSqlSession(); //对象
        NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
        List<News> newsList = newsMapper.selectAll();
        for (News news:newsList) {
            System.out.println(news.getNewsId()+"==="+news.getNewsTitle()+"==="+news.getNewsType().getNewsTypeTitle());
        }
        sqlSession.close();
    }

}
~~~



#### 3. 一对多的映射

实体类

~~~java
package cn.hxzy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

/*
资讯类别表
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class NewsType {
    private Integer newsTypeId;
    private String newsTypeTitle;
    /**
     * 一对多
     */
    private List<News> newsList; //资讯集合
}

~~~



Mapper.xml

~~~xml
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 命名空间..接口的包路径-->
<mapper namespace="cn.hxzy.dao.NewsTypeMapper">
    <resultMap id="userList" type="NewsType">
        <id property="newsTypeId" column="newsTypeId"></id>
        <result property="newsTypeTitle" column="newsTypeTitle"></result>
        <!--collection表示的是集合属性  private List<News> newsList -->
        <collection property="newsList" ofType="News">
            <id property="newsId" column="newsId" />
            <result property="newsTitle" column="newsTitle" />
            <result property="newsInfo" column="newsInfo" />
            <result property="newsFrom" column="newsFrom" />
            <result property="newsContent" column="newsContent" />
            <result property="createTime" column="createTime" />
            <result property="newsimg" column="newsimg" />
        </collection>
    </resultMap>

    <select id="getNewsByType" resultMap="userList">
          SELECT *  FROM newsType t1
               LEFT JOIN news t2
                  ON t1.newsTypeId=t2.newsTypeId
    </select>

</mapper>
~~~

接口

~~~java
package cn.hxzy.dao;

import cn.hxzy.pojo.News;
import cn.hxzy.pojo.NewsType;

import java.util.List;

public interface NewsTypeMapper {
    //根据资讯类别去查询所属的资讯信息
    List<NewsType> getNewsByType();
}

~~~

测试

~~~java
package cn.hxzy.dao;

import cn.hxzy.pojo.News;
import cn.hxzy.pojo.NewsType;
import cn.hxzy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class NewsTypeMapperTest {
    @Test
    public void getNewsByType() {
        SqlSession sqlSession = MybatisUtils.creatSqlSession(); //对象
        NewsTypeMapper newsTypeMapper = sqlSession.getMapper(NewsTypeMapper.class);
        List<NewsType> newsTypeList = newsTypeMapper.getNewsByType();
        for (NewsType newsType : newsTypeList) {
            System.out.println(newsType.getNewsTypeId() + "===" + newsType.getNewsTypeTitle());
            for (News news : newsType.getNewsList()) {
                System.out.println(news.getNewsTitle());
            }
        }
        sqlSession.close();
    }
}
~~~



### 七、外部文件配置数据源

编写database.properties文件

~~~properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ticket?serverTimezone=GMT%2B8&useUnicode=true&useSSL=false&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
~~~

说明:

~~~properties
serverTimezone=Asia/Shanghai"
或
serverTimezone=GMT%2B8
或
serverTimezone=UTC
~~~

核心配置文件中引入

~~~xml
<!--把数据库的连接信息配置在properties文件之下-->
<properties resource="database.properties"/>
~~~

更改数据源配置信息

~~~xml
<!--数据源配置信息-->
<dataSource type="POOLED">
    <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>
~~~

**映射器(mappers)**

1、使用相对于类路径的资源引用,默认会在resource资源目录下去找

~~~xml
<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
~~~

2、使用完全限定资源定位符(URL)

~~~xml
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
~~~

后续再讲

3、使用映射器接口实现类的完全限定类名

~~~xml
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
~~~

4、将包内的映射器接口实现全部注册为映射器

~~~xml
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>
~~~



**setting设置项**

~~~xml
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--映射方式默认的自动映射关闭-->
    <setting name="autoMappingBehavior" value="PARTIAL"/>
    <!--mybatis的日志-->
    <setting name="logImpl" value="STDOUT_LOGGING"/> <!--mybatis标准日志-->
</settings>
~~~





### 八、动态SQL

编写代码的时候,写的是基本结构,当程序运行的时候,会根据条件重新拼接SQL语句,从而生成新的SQL语句。

#### 8.1 if....where语句块

~~~xml
<select id="selectBySearch" resultType="Train" parameterType="Train" >
    SELECT * FROM train
    <where>
        <if test="train.startStation!=null or aa!=''">
            and startStation=#{train.startStation}
        </if>
        <if test="train.startTime!=null">
            and startTime=#{train.startTime}
        </if>
    </where>
</select>
~~~

**mybatis使用LocalDateTime**

把Date改造为LocalDateTime后,如果报红,则打开file-project structrue-modules 模块 language leave:提升一下语言版本最低为8以上

如果运行的时候,出现mysql报错信息,则升级Mysql8.0的依赖

注意:mybatis的版本必须为3.4.5+以上的版本,推荐使用3.5以上的版本。

~~~xml
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>
~~~



#### 8.2 choose、when、otherwise

日期函数:

~~~sql
SELECT * FROM train_ticket
   WHERE DATE_FORMAT(start_date,'%Y-%m-%d')='2022-06-22';
~~~

map入参,注意:map写在表达式中,

~~~xml
<select id="selectNewsListSearch" parameterType="java.util.Map" resultMap="newsList">
    SELECT t1.*,t2.* FROM news t1
    LEFT JOIN newstype t2
    ON t1.`newsTypeId`=t2.`newstype_id`
    <where>
        <choose>
            <when test="newsTypeId!=null">
                and t2.newstype_id=#{map.newsTypeId}
            </when>
            <when test="newsTypeTitle!=null">
                and t2.newstype_title=#{map.newsTypeTitle}
            </when>
            <otherwise>
                and 1=1
            </otherwise>
        </choose>
    </where>
</select>
~~~

模糊查询,使用concat函数拼接 % 百分号

~~~xml
 AND news_title like concat("%",#{newsTitle},"%")
~~~



#### 8.3 自定义 trim 元素

万能牌

~~~XML
<select id="selectBySearch" resultType="Train" parameterType="Train">
    <trim prefix="where" prefixOverrides="AND | OR">
        <if test="train.startStation!=null">
            AND startStation=#{train.startStation}
        </if>
        <if test="train.startTime!=null">
            and startTime=#{train.startTime}
        </if>
    </trim>
</select>
~~~

trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆

盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim

来代替where元素的功能。

####  8.4 set语句

一般用于更新的情况

~~~xml
<update id="update">
    UPDATE train_ticket
    <set>
        <if test="trainTicket.tripsName!=null">
            trips_name=#{trainTicket.tripsName},
        </if>
        <if test="trainTicket.tripsTypeId!=0">
            trips_type_id=#{trainTicket.tripsTypeId},
        </if>
        <if test="trainTicket.departureTerminal!=null">
            departure_terminal=#{trainTicket.departureTerminal},
        </if>
        <if test="trainTicket.destination!=null">
            destination=#{trainTicket.destination},
        </if>
        <if test="trainTicket.startDate!=null">
            start_date=#{trainTicket.startDate},
        </if>
        <if test="trainTicket.endDate!=null">
            end_date=#{trainTicket.endDate},
        </if>
        <if test="trainTicket.lasted!=0.0">
            lasted=#{trainTicket.lasted},
        </if>
    </set>
    where ticket_id=#{trainTicket.ticketId}
</update>
~~~

trim替换set示例:

~~~xml
<update id="updateNews">
    UPDATE news
    <trim prefix="set" suffixOverrides=",">
        <if test="newsTitle!=null">
            news_title=#{newsTitle},
        </if>
        <if test="categroy.categroyId!=0">
            categroy_id=#{categroy.categroyId},
        </if>
        <if test="newsAuthor!=null">
            news_author=#{newsAuthor},
        </if>
        <if test="createTime!=null">
            create_time=#{createTime},
        </if>
        <if test="newsContent!=null">
            news_content=#{newsContent},
        </if>
    </trim>
    WHERE news_id=#{newsId}
</update>
~~~



#### 8.5 foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:

~~~xml
<delete id="delete" parameterType="java.util.List">
    DELETE FROM train_ticket
    WHERE ticket_id IN
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</delete>
~~~

注意:如果使用数组入参,则需要添加注解

~~~java
int batchDelete(@Param("arr") int [] arr);
~~~

~~~xml
<foreach collection="arr" ...></foreach>
~~~



### 9、分页插件

#### 9.1 在pom.xml添加依赖

~~~xml
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</dependency>
~~~

#### 9.2 在Mybatis核心配置文件中设置分页插件

在setting之下添加插件配置

~~~xml
<plugins>
     <!--设置分页插件-->
     <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
~~~

#### 9.3 测试分页功能

~~~java
/**limit index,pageSize
 * index:当前页的起始索引
 * pageSize:每页显示的条数
 * pageNum:表示当前页的页码
 * index=(pageNum-1)*pageSize
 * @author:mengshujun
 * @createTime: 2024-03-26 14:58:13 星期二
 */
@Test
public void test5(){
    SqlSession sqlSession = MyBatisUtils.openSession();
        NewsMapper newsMapper = sqlSession.getMapper(NewsMapper.class);
        Page<News> pages = PageHelper.startPage(2, 5);
        List<News> list = newsMapper.selectNewsList();
        for (News news : list) {
            System.out.println(news);
        }
        System.out.println("================");
        int pageNum = pages.getPages();
        System.out.println("总页数:"+pageNum);
        long total = pages.getTotal();
        System.out.println("总记录数:"+total);
        int num = pages.getPageNum();
        System.out.println("当前的页码:"+num);
}

~~~



### 十、注解开发

#### 10.1 单表操作

@Insert:实现新增 

@Update:实现更新 

@Delete:实现删除 

@Select:实现查询 

然后在Mapper接口的方法上,加上特定的注解实现对数据库表的操作

例如:

```java
@Select("select * from user")
List<User> findAllTest();

@Select("select * from user where id = #{id}")
User findByIdTest(int id);

@Insert("insert into user values(#{id},#{username},#{password},#{birthday});")
void saveTest(User user);

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

@Update("update user set username=#{username},password=#{password} where id = #{id};")
void updateTest(User user);
```

#### 10.2 动态SQL

~~~java
@Update({"<script>",
         "update news ",
         " <set>",
         " <if test='news.newsId!=0'>newsId=#{news.newsId},</if>",
         " <if test='news.newsTitle!=null'>newsTitle=#{news.newsTitle},</if>",
         " </set>",
         "<where>",
         "newsId=#{news.newsId}",
         "</where>",
         "</script>"}
       )
int updateNews(@Param("news") News news);
~~~





### 十一、注解实现复杂映射开发

@Results:可以与@Result 一起使用,封装多个结果集,代替`<resultMap>` 

@Result:实现结果集封装

1. column:数据库的列名
2. property:需要装配的属性名
3. one:需要使用的@One 注解(@Result(one=@One)()))
4. many:需要使用的@Many 注解(@Result(many=@many)()))

@One:实现一对一结果集封装,代替`<assocation>` 使用格式:@Result(column=" ",property="",one=@One(select="")) 

@Many:实现一对多结果集封装,代替`<collection>` 使用格式:@Result(property="",column="",many=@Many(select="")) 

实体类:

News实体类

~~~java
package cn.hxzy.news.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;


@Data
@NoArgsConstructor
@AllArgsConstructor
public class News implements Serializable {
    private int newsId;
    private String newsTitle;
    private String newsInfo;
    private String newsFrom;
    private String newsContent;
    private Date createTime;
    private String newsimg;
    private NewsType newsType; //自定义的类型使用的时候,需要创建对象(赋值是看业务)(一对一)

}

~~~

NewsType实体类

~~~java
package cn.hxzy.news.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class NewsType implements Serializable {
    private int newsTypeId;
    private String newsTypeTitle;

    //一对多
    private List<News> newsList;

    public NewsType(String newsTypeTitle) {
        this.newsTypeTitle = newsTypeTitle;
    }

    public NewsType(int newsTypeId, String newsTypeTitle) {
        this.newsTypeId = newsTypeId;
        this.newsTypeTitle = newsTypeTitle;
    }
}

~~~



#### 11.1 一对一查询

当查询一个表,需要把另一个表的数据也同时查询出来时

NewsMapper接口

~~~java
public interface NewsMapper {

    @Select("select * from news")
    @Results({
            @Result(id = true, column = "newsId", property = "newsId"),
            @Result(column = "newsTitle", property = "newsTitle"),
            @Result(column = "newsInfo", property = "newsInfo"),
            @Result(column = "newsFrom", property = "newsFrom"),
            @Result(column = "newsContent", property = "newsContent"),
            @Result(column = "createTime", property = "createTime"),
            @Result(column = "newsimg", property = "newsimg"),
            @Result(column = "newsTypeId",property = "newsType",
                    javaType = NewsType.class, one = @One(select = "cn.hxzy.news.mapper.NewsTypeMapper.selectNewsType"))
    })
    List<News> selectNewsList();
}
~~~

NewsTypeMapper接口

~~~java
package cn.hxzy.news.mapper;

import cn.hxzy.news.entity.NewsType;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface NewsTypeMapper {

    @Select("select * from newsType where newstype_id=#{newsTypeId}")
    @Results({
            @Result(id = true,column = "newstype_id",property = "newsTypeId"),
            @Result(column = "newstype_title",property = "newsTypeTitle")
    })
    NewsType selectNewsType(@Param("newsTypeId") int newsTypeId);
}
~~~

#### 12.2 一对多查询

1.查询单个类别对应多个资讯的情况

NewsMapper

~~~java
public interface NewsMapper {
    @Select("select * from news where newsTypeId=#{newsTypeId}")
    List<News> selectNewsListByTypeId(int newsTypeId);
}    
~~~

NewsTypeMapper

~~~java
public interface NewsTypeMapper {

    @Select("select * from newsType where newstype_id=#{newsTypeId}")
    @Results({
            @Result(id = true,column = "newstype_id",property = "newsTypeId"),
            @Result(column = "newstype_title",property = "newsTypeTitle"),
            @Result(column = "newstype_id",property = "newsList",javaType = List.class,
            many = @Many(select = "cn.hxzy.news.mapper.NewsMapper.selectNewsListByTypeId"))
    })
    NewsType selectNewsType(@Param("newsTypeId") int newsTypeId);
}
~~~

2.查询多个类别对应多个资讯的情况

NewsMapper

~~~java
public interface NewsMapper {
    @Select("select * from news where newsTypeId=#{newsTypeId}")
    List<News> selectNewsListByTypeId(int newsTypeId);
}    
~~~

NewsTypeMapper

~~~java
@Select("select * from newsType")
@Results({
    @Result(id = true,column = "newstype_id",property = "newsTypeId"),
    @Result(column = "newstype_title",property = "newsTypeTitle"),
    @Result(column = "newstype_id",property = "newsList",javaType = List.class,
            many = @Many(select = "cn.hxzy.news.mapper.NewsMapper.selectNewsListByTypeId"))
})
List<NewsType> selectNewsTypeList();
~~~

### 十二、SQL语句块

~~~xml
<sql id="columns">
    t1.newsId,
    t1.`newsTypeId`,
    t1.`newsTitle`,
    t1.`newsInfo`,
    t1.`newsFrom`,
    t1.`newsContent`,
    t1.`createTime`,
    t1.`newsimg`,
    t2.`newstype_id`,
    t2.`newstype_title`
</sql>

<sql id="newsSearch">
    SELECT
    <include refid="columns"/>
    FROM news t1
    LEFT JOIN newstype t2 ON t1.`newsTypeId`=t2.`newstype_id`
</sql>

<select id="selectNewsListSearch" parameterType="java.util.Map" resultMap="newsList">

    <include refid="newsSearch"/>
    <where>
        <choose>
            <when test="newsTypeId!=null">
                and t2.newstype_id=#{newsTypeId}
            </when>
            <when test="newsTypeTitle!=null">
                and t2.newstype_title=#{newsTypeTitle}
            </when>
            <otherwise>
                and 1=1
            </otherwise>
        </choose>
    </where>
</select>
~~~

### 十三、mybatis缓存

缓存是只针对查询业务有效,增删改操作会更新缓存。

#### 13.1 一级缓存

作用范围在一个sqlsession之间,如果中间有增删改操作会更新缓存,或者手动关闭sqlSession。

一级缓存不需要自己打开或者关闭,默认开启的,也关闭不了。

一级缓存不可以进行数据共享

#### 13.2 二级缓存

二级缓存可以进行数据共享,在线程中可以进行数据共享。
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值