• 手把手学Java之Mybatis


    小感悟:

        自学Java也有一年了,基本上都是学习基础的教程,Java水很深,前面学习新知识后面忘了老知识,我也不知道关于Java中的东西反反复复的敲了多少次。大学同学在某个培训机构里面培训了仅仅三个月就去工作了,笔者和培训后的同学交流后感觉技术不过如此。Java的学习道路很是艰难,虽然我毕业后没能去从事软件开发,但是我想用时间来沉淀一下自己的技术,今天我们就来谈谈Mybatis技术。

    使用技术:Maven+Mybatis

    开发工具:IDEA

    1 HelloWorld

    创建Maven项目并且在pom.xml文件中导入Mybatis依赖

    <dependency>

    <groupId>org.mybatis</groupId>

    <artifactId>mybatis</artifactId>

    <version>RELEASE</version>

    </dependency>

    数据库中创建一个book表

    CREATE TABLE `book` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `name` varchar(50) DEFAULT NULL,

      `author` varchar(50) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    创建实体类并且生成set和get以及toString方法


    book实体类

    mybatis参考文档中复制约束文件(Mybatis官方参考网址)

    http://www.mybatis.org/mybatis-3/zh/getting-started.html

    参考官方文档创建mybatis核心配置文件


    mybatis核心配置文件

    pom.xml文件中引入Mysql驱动依赖

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>RELEASE</version>

    </dependency>

    创建数据库配置文件db.properties

    db.driver=com.mysql.jdbc.Driver

    db.url=jdbc:mysql:///test_mybatis

    db.username=root

    db.password=xxxxxxxxxxx

    在mybatis核心配置文件中引入数据库配置文件


    mybatis核心配置文件中引入数据库配置

    将${}里面的内容更改为${db.properties}

    创建mapper包并且在该包下面创建接口和xml文件


    Mapper

    BookMapper接口中添加内容为

    public interface BookMapper {

    int addBook(Book book);

    }

    BookMapper.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.mapper.BookMapper">

    <insert id="addBook">

    insert into book set name="浅谈mybatis",author="孤芳不自赏";

    </insert>

    </mapper>

    核心配置文件中引入mapper.xml文件


    mybatis核心配置文件中引入mapper.xml文件

    创建测试类

    public class test_mybatis {

    public static void main(String[] args)throws IOException {

    //读取mybatis核心配置文件,抛出异常

            InputStream r = Resources.getResourceAsStream("mybatis-conf.xml");

    //创建sqlSession工厂

            SqlSessionFactory sqf =new SqlSessionFactoryBuilder().build(r);

    //通过工厂来获取session对象

            SqlSession session = sqf.openSession();

    //通过session来进行响应的crud操作

    /**

    * 添加操作

    */

            int i = session.insert("addBook");

    session.commit();

    if (i>0){

    System.out.println("添加成功!");

    }else{

    System.out.println("添加失败!");

    }

    session.close();

    }

    }

    此时运行会报如下错误(未发现核心配置文件)

    Cause: java.io.IOException: Could not find resource com/mapper/BookMapper.xml

    pom.xml文件中添加内容如下

    <build>

    <resources>

    <resource>

    <directory>src/main/java</directory>

    <includes>

    <include>**/*.xml</include>

    </includes>

    </resource>

    <resource>

    <directory>src/main/resources</directory>

    </resource>

    </resources>

    </build>

    此时运行还会报错

    You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

    在db.properties中的url后面添加内容为

    ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC


    db.properties

    然后运行结果:


    成功运行控制台打印

    数据库表中


    添加成功后的结果

    此时已经成功的用Mybatis书写了一个HelloWorld程序!

    本节视频教程:
    本节代码源码资料:


    2 日志打印

    pom.xml文件中引入log4j依赖

    <dependency>

    <groupId>log4j</groupId>

    <artifactId>log4j</artifactId>

    <version>RELEASE</version>

    </dependency>

    resources下面创建log4j.properties文件,且里面添加如下内容

    log4j.rootLogger= DEBUG,stdout

    log4j.logger.org.mybatis=DEBUG

    ###输出信息到控制抬 ###

    log4j.appender.stdout= org.apache.log4j.ConsoleAppender

    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout

    log4j.appender.stdout.layout.ConversionPattern =%C %p %m %n

    此时在运行我们的项目就会发现控制台多出


    控制台打印sql语句

    3 参数传递

    BookMapper.xml文件中添加

    <insert id="addBook" parameterType="com.model.Book">

    insert into book set name=#{name},author=#{author};

    </insert>

    测试类中

    public class test_mybatis {

    private SqlSessionsession;

    @Before

        public void before()throws IOException {

    //读取mybatis核心配置文件,抛出异常

            InputStream r = Resources.getResourceAsStream("mybatis-conf.xml");

    //创建sqlSession工厂

            SqlSessionFactory sqf =new SqlSessionFactoryBuilder().build(r);

    //通过工厂来获取session对象

            session = sqf.openSession();

    //通过session来进行响应的crud操作

        }

    @After

        public void after(){

    session.close();

    }

    @Test

        public void test1(){

    Book book =new Book();

    book.setName("浅谈mybatis");

    book.setAuthor("孤芳不自赏");

    int i =session.insert("addBook",book);

    session.commit();

    if (i>0) {

    System.out.println("添加成功");

    }else{

    System.out.println("添加失败");

    }

    }

    }


    4 自定义Dao方法

    之前当我们想实现crud操作时候都是调用seesion里面的方法,现在我们自己来创建自己的方法。


    之前实现curd都是调用sessio中的

    在BookMapper中添加接口

    public interface BookMapper {

    int addBook(Book book);

    int updateBook(Book book);

    int deleteBook();

    }

    此时我们在测试类里面就可以调用自己的接口了


    调用自己书写的Mapper接口

    BookMapper.xml文件中添加更新方法

    <insert id="updateBook" parameterType="com.model.Book">

    update book set author=#{author} where id=#{id}

    </insert>

    测试类中

    @Test

    public void test2(){

    BookMapper mapper =session.getMapper(BookMapper.class);

    Book book =new Book();

    book.setId(30);

    book.setAuthor("MybatisBoy");

    int i = mapper.updateBook(book);

    if (i>0) {

    System.out.println("更新成功");

    }else{

    System.out.println("更新失败");

    }

    session.commit();

    }

    更新结果为


    更新数据库结果

    5 简化mybatis配置

    5.1创建mapper.xml模板


    创建mapper.xml模板

    添加内容

    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    <mapper namespace="#[[$Title$]]#">

    </mapper>

    使用刚刚创建好的模板来创建一个testMapper.xml


    创建一个testMppaer

    创建的后的结果

    声明:还可以用来简化db.properties配置文件哦!自己动手尝试一下吧。

    5.2 给类起别名

    细心的同学会发现我们写插入语句时候的parameterType类型往往是类的路径,能不能进一步简化呢?答案是当然可以了。


    简化前

    简化后

    核心配置文件中配置

    虽然简化了一个类,但是当类多的时候每次都要在配置文件中配置这样依然很繁琐。于是可以这样配置。


    给model下的所有类起别名

    每次添加一个mapper.xml都要在核心配置文件中引入,这样依然很麻烦。


    简化前

    简化后

    6  类型转换

    mybatis中基本的类型都能进行转换。加入我想将Java中的一个List集合的数据保存都数据库中varchar类型的字段中那么如何保存呢?

    给book表添加字段


    book表中添加favorties字段

    实体类中添加字段并且生成set和get方法


    实体类中添加favorities字段

    自己创建类型转换类并且实现TypeHandler接口

    配置类上面要添加注解

    @MappedJdbcTypes(JdbcType.VARBINARY)

    @MappedTypes(List.class)

    public class MyTypeHandlerimplements TypeHandler> {

    public void setParameter(PreparedStatement preparedStatement,int i, List strings, JdbcType jdbcType)throws SQLException {

    /**

    * 在这个里面将List集合中的数据全部处理为字符串

    * i 插入的第几个位置

    * strings为List中的数据

    */

     StringBuffer sb =new StringBuffer();

    for (String s : strings) {

    sb.append(s).append(",");

    }

    preparedStatement.setString(i,sb.toString());

    }

    public List getResult(ResultSet resultSet, String s)throws SQLException {

    return null;

    }

    public List getResult(ResultSet resultSet,int i)throws SQLException {

    return null;

    }

    public List getResult(CallableStatement callableStatement,int i)throws SQLException {

    return null;

    }

    }

    mapper.xml文件中添加

    <insert id="addBook" parameterType="book"> insert into book set name=#{name},favorities=#{favorities,typeHandler=com.config.MyTypeHandler}</insert>

    测试类中

    @Test

    public void test1(){

    List list =new ArrayList();

    list.add("Java");

    list.add("C");

    list.add("C++");

    list.add("Objc++");

    Book book =new Book();

    book.setName("浅谈mybatis");

    book.setAuthor("孤芳不自赏");

    book.setFavorities(list);

    int i =session.insert("addBook",book);

    session.commit();

    if (i>0) {

    System.out.println("添加成功");

    }else{

    System.out.println("添加失败");

    }

    }

    控制台打印的 sql为


    添加list集合

    数据库中


    数据库中的结果

    我们成功的添加之后那么如何获取?

    mapper中添加接口

    List<Book> getAllBooks();

    mapper.xml文件中查询全部

    <select id="getAllBooks" resultType="book">

    select* from book;

    </select>

    测试类中书写

    @Test

    public void test_getAllBooks(){

    BookMapper mapper =session.getMapper(BookMapper.class);

    List list = mapper.getAllBooks();

    if (list !=null) {

    for (Book book : list) {

    System.out.println(book);

    }

    }

    }

    经过一番准备后发现测试结果是这样的.


    查询全部的测试结果

    emmm.....此时心里是不是凉凉~~

    好了开始放大招了!!

    核心配置类中配置别名


    配置自定义类的别名

    将字符串类打回List原形


    将字符串打回List集合原形

    此时在执行结果为


    配置后的查询结果

    7 $和#有啥区别

    这个问题相比参加过Java面试的时候都遇到过,下面直接来看

    7.1使用$

    接口

    Book getBookById(Integer id);

    Mapper.xml配置文件中

    <select id="getBookById" resultType="book">

    select* from book where id=${id}

    </select>

    测试类为

    @Test

      public void test_getOneBook(){

    BookMapper mapper =session.getMapper(BookMapper.class);

    Book book = mapper.getBookById(29);

    if (book !=null) {

    System.out.println(book);

    }

    }

    }

    控制台sql为


    使用$的结果

    此处的Id为Integer类型,假如为String类型

    接口中

    Book getBookById(String id);

    Mapper.xml配置文件中

    <select id="getBookById" resultType="book" parameterType="string">

    select* from book where id=${id}

    </select>

    测试类

    @Test

      public void test_getOneBook(){

    BookMapper mapper =session.getMapper(BookMapper.class);

    Book book = mapper.getBookById("29");

    if (book !=null) {

    System.out.println(book);

    }

    }

    }

    控制台sql为


    id为String类型时候(前)

    emm....貌似没看出来变化啊!!

    But~~更该测试类

    @Test

      public void test_getOneBook(){

    BookMapper mapper =session.getMapper(BookMapper.class);

    Book book = mapper.getBookById("29 or id in (30,31)");

    if (book !=null) {

    System.out.println(book);

    }

    }

    再次运行


    id为String类型时候(后)

    且不说返回的结果如何获取,是不是发生了sql注入???!sql注入多可怕!!


    7.2 使用#

    将$更改为#

    <select id="getBookById" resultType="book" parameterType="string">

    select* from book where id=#{id}

    </select>


    使用#

    说了这么就是让大家对#和$又更深的认识,不懂的还可以参考以下博客:Mybatis中的#和$到底有啥区别


    8 传递其他值

    之前传递的要么是Integer类型要么是String类型要么是对象类型 。如何传递一个Map对象呢?

    添加接口

    int insertBook(HashMap map);

    测试类中

    @Test

    public void test_insertOneBook(){

    HashMap map =new HashMap();

    map.put("name","浅谈JavaEE");

    map.put("author","孤芳不自赏");

    BookMapper mapper =session.getMapper(BookMapper.class);

    int i = mapper.insertBook(map);

    session.commit();

    }

    mapper.xml文件中

    <insert id="insertBook" parameterType="HashMap">

    insert into book set name=#{name},author=#{author}

    </insert>

    控制台中


    添加map类型

    数据中


    数据库添加的字段

    如何取出来,接口

    HashMap<String,String> getBookByIdResultMap(Integer uid);

    核心配置文件中

    <select id="getBookByIdResultMap" resultType="java.util.HashMap">

    select* from book where id=#{uid}

    </select>

    测试类中

    @Test

      public void test_insertOneBook(){

    //      HashMap map = new HashMap();

    //      map.put("name","浅谈JavaEE");

    //      map.put("author","孤芳不自赏");

          BookMapper mapper =session.getMapper(BookMapper.class);

    //      int i = mapper.insertBook(map);

    //      session.commit();

          HashMap map = mapper.getBookByIdResultMap(34);

    System.out.println(map);

    }

    }


     

    对比观察一下,map返回的是集合,之前的返回的是对象

            {author=孤芳不自赏, name=浅谈JavaEE, id=34}  //map集合返回 

    Book{author=孤芳不自赏, name=浅谈JavaEE, id=34}  //之前的返回


    9 resultMap

    9.1通过起别名解决

    问题:当数据库中的字段和java实体类中的字段不对应时候,当自动查询时候就无法映射上,此时可以通过给字段其别名的方式来实现,但是每次都要给字段起别名就很麻烦,可以通过抽出该别名字段的方式,但是使用resultMap能很好的解决这一问题。

    创建author表


    author表

    CREATE TABLE `author` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `author_name` varchar(50) DEFAULT NULL,

      `book_name` varchar(50) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    创建实体类(注意实体类的属性名和数据库的字段不对应)


    author实体类

    Mapper配置文件中


    mapper配置文件

        测试类中


    测试类

    结果有两个为Null


    测试结果

    通过起别名解决


    起别名后的结果

    9.2通过resultMap解决

    配置文件中书写

    <resultMap id="MyResultMap" type="com.model.Author">

    <id column="id" property="id"></id>

    <result column="author_name" property="authorName"></result>

    <result column="book_name" property="bookName"></result>

    </resultMap>

    <select id="getAuthorList" resultMap="MyResultMap">

    select* from author;

    </select>

    其中

    column对应的是数据库中的字段

    property对应的是实体类中的字段

    测试结果和上面的一样


    resultMap原理

    9.3 传递多个参数

    当我们想存储bookName和AuthorName这两个字段到数据库表中的时候,但是又不想通过传递实体类来封装,此时该怎么办?

    接口中

    int insertAuthor(String bookName,String authorName);

    xml文件中

    <insert id="insertAuthor" parameterType="string">

    insert into author set book_name=#{bookName},author_name=#{authorName}

    </insert>

    测试

    @Test

    public void test4(){

    AuthorMapper mapper =session.getMapper(AuthorMapper.class);

    int i = mapper.insertAuthor("JavaEE","孤芳不自赏");

    session.commit();

    }

    控制台报错

    org.apache.ibatis.binding.BindingException: Parameter 'bookName' not found

    为了解决这个问题:@Param横空出世

    将接口改为

    int insertAuthor(@Param("bookName") String bookName, @Param("authorName") String authorName);

    此时在运行就可以插入成功了。添加上注解之后就连parameterType也可以不写了。

    最终的mapper为

    <insert id="insertAuthor" >

    insert into author set book_name=#{bookName},author_name=#{authorName}

    </insert>

    @Param的意思就是将bookName注入到mybatis中,当在配置文件中使用的时候,这个名字是认识的,所以就不会报找不到该名字。


    10 动态sql

    在mysql中个人感觉使用频率最高的还是动态sql,动态sql顾名思义,就是sql语句是可以动态的改变的呗。稍微好听的称呼是:动态sql就是可以在sql语句中拼接或组装sql。

    >>foreach

    10.1使用foreach根据传递数组id集合进行查询

    添加接口

    List getAuthorByIds(@Param("ids") Long[] id);

    配置文件中

    <select id="getAuthorByIds" resultMap="MyResultMap">

    select* from author where id in(

    <foreach collection="ids" item="id" separator=",">

    #{id}

    </foreach>

    )

    </select>

    测试类中

    @Test

    public void test5(){

    AuthorMapper mapper =session.getMapper(AuthorMapper.class);

    Long[] ids={1L,5L,6L};

    List list = mapper.getAuthorByIds(ids);

    for (Author author : list) {

    System.out.println(author);

    }

    }

    测试结果


    测试结果

    语句可以进一步的简化

    <select id="getAuthorByIds" resultMap="MyResultMap">

    select* from author where id in

    <foreach collection="ids" item="id" separator="," open="(" close=")">

    #{id}

    </foreach>

    </select>

    如果不起别名的话报错如下


     

    更改为array即可


     

    根据传递id的List集合进行查询。


     

    使用list或者collection


    测试结果

    测试类


    测试类

    10.2 使用foreach实现批量添加

    myqsl数据库中批量添加的方式为

    insert into author(author_name,book_name) VALUES('李白','静夜思'),('李白','蜀道难')

    接口

    int insertManyAuthor( List authors);

    配置文件,注意这个没有close和open属性

    <insert id="insertManyAuthor">

    insert into author(book_name,author_name) value

    <foreach collection="collection" item="authors"  separator=",">

    (#{authors.bookName},#{authors.authorName})

    </foreach>

    </insert>

    测试类

    @Test

    public void insertManyAuthor(){

    AuthorMapper mapper =session.getMapper(AuthorMapper.class);

    ArrayList list =new ArrayList();

    list.add(new Author("冰心","寄小读者"));

    list.add(new Author("滕王阁序","王勃"));

    int i = mapper.insertManyAuthor(list);

    session.commit();

    if (i>0) {

    System.out.println("插入成功");

    }else {

    System.out.println("插入失败");

    }

    }

    结果


    批量添加结果

    >>if

    10.3 if语句

    if语句常用来判断插入的值是否为空

    如之前的根据ids来查询结果


    根据ids查询结果

    But当ids为null时候,就会报错

    List list = mapper.getAuthorByIds(null);

    Caused by: org.apache.ibatis.builder.BuilderException: The expression 'ids' evaluated to a null value.

    之前的sql语句是这样的

    <select id="getAuthorByIds" resultMap="MyResultMap">

    select* from author where id in

    <foreach collection="ids" item="id" separator="," open="(" close=")">

    #{id}

    </foreach>

    </select>

    修改后的sql语句是这样的

    <select id="getAuthorByIds" resultMap="MyResultMap">

    select* from author

    <if test="ids!=null and ids.length>0">

    where id in

    <foreach collection="ids" item="id" separator="," open="(" close=")">

    #{id}

    </foreach>

    </if>

    </select>

    当ids为空时候打印的sql是,即查询全部

    Preparing: select * from author

    >>where

    10.4 where语句

    where和if是一对好基友,经常在一起搭配使用,例如查询一个id大于4且名字带有“李”的所有的用户。


    author表

    接口

    List getAuthorsBySelect(@Param("id") Integer id,@Param("name") String name);

    配置文件中

    <select id="getAuthorsBySelect" resultMap="MyResultMap">

    select* from author

    <where>

    <if test="id!=null and id!=''">

    and id>#{id}

    </if>

    <if test="name!=null and name!=''">

    and  author_name like concat('%',#{name},'%')

    </if>

    </where>

    </select>

    测试类

    @Test

    public void testSelect(){

    AuthorMapper mapper =session.getMapper(AuthorMapper.class);

    List authors = mapper.getAuthorsBySelect(4,"李");

    for (Author author : authors) {

    System.out.println(author);

    }

    }

    结果


    测试结果

    当参数为空时候查询所有

    借此机会给大家普及一下where里面的And的使用 ,一直匹配,直到遇到第一个条件满足时候将前面的and去掉。

    >>set

    10.5 set集合

    接口

    int updateAuthor(Author author);

    配置文件

    <update id="updateAuthor" parameterType="author">

    update author

    <set>

    <if test="authorName!=null and  authorName!=''">

    author_name=#{authorName},

    </if>

    <if test="authorName!=null and  authorName!=''">

    book_name=#{bookName},

    </if>

    </set>

    where id=#{id}

    </update>

    测试类

    @Test

    public void testUpdate(){

    AuthorMapper mapper =session.getMapper(AuthorMapper.class);

    Author author =new Author();

    author.setId(9);

    author.setBookName("冰心散文");

    author.setAuthorName("冰心");

    int i = mapper.updateAuthor(author);

    session.commit();

    if (i>0) {

    System.out.println("更新成功");

    }else{

    System.out.println("更新失败");

    }

    }

    结果


    使用set更新后的

    借此机会给大家普及一下set里面的逗号用 ,一直匹配,将最后一个符合条件的逗号去掉。

    11 主键回填

    11.1当id设置成自增长时

    当向数据库中插入一个字段时候,将插入的所有信息返回包括id。

    将刚刚的配置文件内容更改为

    <update id="updateAuthor" parameterType="author" useGeneratedKeys="true" keyProperty="id" keyColumn="id">

    update author

    <set>

    <if test="authorName!=null and  authorName!=''">

    author_name=#{authorName},

    </if>

    <if test="authorName!=null and  authorName!=''">

    book_name=#{bookName},

    </if>

    </set>

    where id=#{id}

    </update>

    测试类中添加一条语句即可

    System.out.println("主键回填>>>>>>>>>>"+author);

    测试运行结果为


    主键回填结果

    11.2当id不为自增长且为varchar类型时

    创建一个Cat表

    CREATE TABLE `cat` (

      `id` varchar(255) DEFAULT NULL,

      `name` varchar(50) DEFAULT NULL

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    创建实体类

    public class Cat {

    private Stringid;

    private Stringname;

    }

    配置文件中,注意返回值类型是java.lang.String

    <insert id="insertCat">

    <selectKey keyProperty="id" keyColumn="id" order="BEFORE" resultType="java.lang.String">

    select uuid();

    </selectKey>

    insert into cat set id=#{id},name=#{name}

    </insert>

    测试类

    @Test

    public void testCat(){

    CatMapper mapper =session.getMapper(CatMapper.class);

    Cat cat =new Cat();

    cat.setName("小花");

    mapper.insertCat(cat);

    session.commit();

    System.out.println(cat);

    }

    结果


    主键回填测试结果

    12 一对一查询

    创建员工表和部门表两个,一个员工属于一个部门

    部门表

    CREATE TABLE `department` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `dname` varchar(50) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

    员工表,在员工表里面有一个部门表中的id作为字段以此来证明该员工属于那个部门

    CREATE TABLE `employee` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `name` varchar(50) DEFAULT NULL,

      `sex` varchar(10) DEFAULT NULL,

      `age` int(10) DEFAULT NULL,

      `phone` varchar(50) DEFAULT NULL,

      `address` varchar(50) DEFAULT NULL,

      `did` int(10) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

    员工表和部门表之间的关系


    员工表和部门表之间的关系

    创建部门表实体类

    public class Department {

    private Integerid;

    private Stringname;

    }

    创建员工表实体类,并且员工表中包含部门类属性

    public class Employee {

    private Integerid;

    private Stringname;

    private Stringsex;

    private Integerage;

    private Stringphone;

    private Stringaddress;

    private Integerdid;

    private Departmentdepartment;

    }

    部门表中添加内容


    部门表

    员工表


    员工表

    接口

    List<Employee> getAllEmp();

    配置文件

    <select id="getAllEmp" resultType="employee">

    select e.*,d.* from employee e,department d where e.did=d.id

    </select>

    测试类

    @Test

    public void testEmp(){

    EmployeeMapper mapper =session.getMapper(EmployeeMapper.class);

    List list = mapper.getAllEmp();

    for (Employee employee : list) {

    System.out.println(employee);

    }

    }

    结果


    测试结果

    解决办法:自己定义返回类型

    配置文件中

    <resultMap id="myResultMap" type="com.model.Employee">

    <id column="id" property="id"></id>

    <result column="name" property="name"></result>

    <result column="age" property="age"></result>

    <result column="sex" property="sex"></result>

    <result column="address" property="address"></result>

    <result column="phone" property="phone"></result>

    <!--定义一对一映射-->

          <association property="department" javaType="com.model.Department">

    <id column="depId" property="id"></id>

    <result column="depName" property="name"></result>

    </association>

    </resultMap>

    <select id="getAllEmp" resultMap="myResultMap">

    select e.*,d.id as depId,d.dname as depName from employee e,department d where e.did=d.id

    </select>

    配置文件解释


    配置文件说明

    结果


    一对一查询结果

    13  一对多

    员工和角色是一对多的关系

    创建员工表

    CREATE TABLE `employee` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `name` varchar(50) DEFAULT NULL,

      `sex` varchar(10) DEFAULT NULL,

      `age` int(10) DEFAULT NULL,

      `phone` varchar(50) DEFAULT NULL,

      `address` varchar(50) DEFAULT NULL,

      `did` int(10) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

    创建角色表

    CREATE TABLE `role` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `rname` varchar(50) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

    创建员工角色表

    CREATE TABLE `e_r` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `eid` int(10) DEFAULT NULL,

      `rid` int(10) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

    创建部门表

    CREATE TABLE `department` (

      `id` int(10) NOT NULL AUTO_INCREMENT,

      `dname` varchar(50) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

    员工表中的内容


    员工表

    角色表中的内容


    角色表

    员工角色表中的内容


    员工角色表

    部门表中的内容


    部门表

    接口

    List<Employee> getAllEmpAndRoles();

    配置文件

    <?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.mapper.EmployeeMapper">

    <resultMap id="myResultMap" type="com.model.Employee">

    <id column="id" property="id"></id>

    <result column="name" property="name"></result>

    <result column="age" property="age"></result>

    <result column="sex" property="sex"></result>

    <result column="address" property="address"></result>

    <result column="phone" property="phone"></result>

            <association property="department" javaType="com.model.Department">

    <id column="depId" property="id"></id>

    <result column="depName" property="name"></result>

    </association>

    <!--定义一对一映射 注意是ofType-->

            <collection property="roles" ofType="com.model.Role">

    <id column="rid" property="id"></id>

    <result column="rName" property="name"></result>

    </collection>

    </resultMap>

    <select id="getAllEmp" resultMap="myResultMap">

    select e.*,d.id as depId,d.dname as depName from employee e,department d where e.did=d.id

    </select>

    <select id="getAllEmpAndRoles" resultMap="myResultMap">

    select e.*,er.*,r.id as rid,GROUP_CONCAT(r.rname) as rName,d.id as depId,d.dname as depName from employee e,e_r er,department d, role r

    where e.did=d.id and er.eid=e.id and er.rid=r.id

    GROUP BY e.id

    </select>

    </mapper>

    测试类

    @Test

    public void testEmp(){

    EmployeeMapper mapper =session.getMapper(EmployeeMapper.class);

    List list = mapper.getAllEmpAndRoles();

    for (Employee employee : list) {

    System.out.println(employee);

    }

    }

    结果


    查询结果

    问题:

    如果查询结果是一下这样的,如何将rName合并成上图


    更改前的查询结果

    使用GROUP_CONCAT(要合并的字段)......   GROUP BY 用户表.id

    14 延迟加载

    11.1一对迟加载

    什么是迟加载?举个栗子来说了吧。

    员工表中的属性

    public class Employee {

    private Integerid;

    private Stringname;

    private Stringsex;

    private Integerage;

    private Stringphone;

    private Stringaddress;

    private Integerdid;

    private Department department;

    private List<Role> roles;

    }

    当我只想获取员工表中的基本字段(除了)department和roles

    接口中,注意员工接口中声明部门属性。

    public interface EmployeeMapper {

    List getAllEmp();

    List getAllEmp(Integer id);

    List getAllEmpAndRoles();

    Department getEepById(Integer did);

    }

    配置文件中


    配置文件中

    测试类


    测试类

    结果


    结果

    添加懒加载


    添加懒加载

    结果


    结果

    当想获取Department属性时候在加载

    测试类中


    获取department

    结果


    结果

    11.2一对多迟加载

    接口中

    List<Role> getRoles(Integer id);

    配置文件中


    配置文件中

    配置文件中

    测试文件中


    测试文件

    结果


    结果

    12  缓存

    mybatis一级缓存即查询缓存

    查询两次只执行一次查询语句


    一级缓存用例

    一级缓存的作用域是session,session结束后缓存停止。

    二级缓存的作用域是sqlSession

  • 相关阅读:
    Android 自定义View修炼-Android 实现自定义的卫星式菜单(弧形菜单)View
    Android中SurfaceView的使用详解
    Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View
    Android 自定义View修炼-实现自定义圆形、圆角和椭圆ImageView(使用Xfermode图形渲染方法)
    Android 自定义View修炼-Android实现圆形、圆角和椭圆自定义图片View(使用BitmapShader图形渲染方法)
    框架 Spring Boot 技术入门到整合 8-1 Springboot整合Mybatis-使用generatorConfig生成mapper以及pojo
    框架 Spring Boot 技术入门到整合 7-3 Springboot配置全局的异常捕获 -同时兼容web和ajax
    框架 Spring Boot 技术入门到整合 7-2 Springboot配置全局的异常捕获 -ajax形式
    框架 Spring Boot 技术入门到整合 7-1 Springboot配置全局的异常捕获 -web页面跳转
    框架 Spring Boot 技术入门到整合 6-3 thymeleaf 常用标签的使用方法
  • 原文地址:https://www.cnblogs.com/gfbzs/p/12518525.html
Copyright © 2020-2023  润新知