进阶内容

准备

jdbc.url=jdbc:mysql://192.168.208.192:3306/test?characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

jdbc.properties

log4j.rootLogger = debug,stdout,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j.properties

<?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"/>

    <!--别名扫描-->
    <typeAliases>
        <package name="com.zze.mybatis.pojo" />
    </typeAliases>

    <!-- 和 spring 整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池-->
            <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>
        </environment>
    </environments>

    <!-- 加载映射文件 -->
    <mappers>
        <package name="com.zze.mybatis.mapper"/>
    </mappers>
</configuration>

mybatis/SqlMapConfig.xml

package com.zze.mybatis.pojo;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private Date birthday;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

com.zze.mybatis.pojo.User

package com.zze.mybatis.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        // 创建 SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建核心配置文件的输入流
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建 Session 工厂
        sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }

    /**
     * 打开一个 Session
     *
     * @return SqlSession 实例
     */
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession();
    }

    /**
     * 打开一个 Session
     *
     * @param autoCommit 是否自动提交事务
     * @return SqlSession 实例
     */
    public static SqlSession openSession(Boolean autoCommit) {
        return sqlSessionFactory.openSession(autoCommit);
    }
}

com.zze.mybatis.util.SqlSessionFactoryUtil

<?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.zze.mybatis</groupId>
    <artifactId>mybatis_test2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

pom.xml

传递被包装的pojo

package com.zze.mybatis.pojo;

public class QueryVO {
    private User user;

    public User getUser() {
        return user;
    }

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

com.zze.mybatis.pojo.QueryVO

<?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.zze.mybatis.mapper.UserMapper">
    <select id="getByQueryVO" parameterType="queryvo" resultType="user">
        select id,name,birthday from user where name like '%${user.name}%'
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.QueryVO;
import com.zze.mybatis.pojo.User;

public interface UserMapper {
    User getByQueryVO(QueryVO queryVO);
}

com.zze.mybatis.mapper.UserMapper

@Test
public void test() {
    SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    QueryVO queryVO = new QueryVO();
    User user = new User();
    user.setName("张");
    queryVO.setUser(user);
    User user1 = mapper.getByQueryVO(queryVO);
    System.out.println(user1);
  /*
  ==>  Preparing: select name,age,birthday,uuid from user where name like '%张%'
   */
}

test

标签使用

字段映射-resultMap

如果表字段名与 pojo 属性名不一致,则可通过 resultMap 标签配置表字段与 pojo 属性的映射关系:

<?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.zze.mybatis.mapper.UserMapper">
    <resultMap id="userMap" type="user">
        <!--
        id 配置对应主键字段
            property:属性名
            column:字段名
        -->
        <id property="id" column="uid"/>
        <!--
        result 配置普通属性字段
            property:属性名
            column:字段名
        -->
        <result property="name" column="username"/>
        <!--
        非关联查询时
        属性名与字段名相同的 result 映射可以省略不写
        -->
        <!--<result property="birthday" column="birthday"/>-->
    </resultMap>

    <select id="getAll" resultMap="userMap">
        select id uid,name username,birthday from user;
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getAll();
}

com.zze.mybatis.mapper.UserMapper

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class MyBatisTest {
    private UserMapper userMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void test() {
        List<User> all = userMapper.getAll();
        for (User user : all) {
            System.out.println(user);
        }
        /*
        ==>  Preparing: select id uid,name username,birthday from user;
         */
    }
}

test

动态sql-where&if

当 sql 条件需要动态拼接时,可以使用 where 和 if 标签:

<?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.zze.mybatis.mapper.UserMapper">
    <select id="getByUser" resultType="user" parameterType="user">
        select id,name,birthday from user
        <where>
            <if test="name!=null and name!=''">
                name like '%${name}%'
            </if>
        </where>
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getByUser(User user);
}

com.zze.mybatis.mapper.UserMapper

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class MyBatisTest {
    private UserMapper userMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void test() {
        User user = new User();
        user.setName("张");
        List<User> userList1 = userMapper.getByUser(user);
        userList1.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select id,name,birthday from user WHERE name like '%张%'
         */
        user.setName(null);
        List<User> userList2 = userMapper.getByUser(user);
        userList2.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select id,name,birthday from user
         */
    }
}

test

sql片段-sql&include

当一段 sql 要被频繁在多处使用时,可以将这段 sql 单独抽取出来:

<?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.zze.mybatis.mapper.UserMapper">
    <sql id="userAllField">
      id,name,birthday
    </sql>
    <select id="getAll" resultType="user">
        select
        <include refid="userAllField"/>
        from user
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getAll();
}

com.zze.mybatis.mapper.UserMapper

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class MyBatisTest {
    private UserMapper userMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void test() {
        List<User> userList = userMapper.getAll();
        userList.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select id,name,birthday from user
         */
    }
}

test

循环-foreach

编写 sql 时也可以通过传入集合来动态拼装条件:

package com.zze.mybatis.pojo;

import java.util.List;

public class QueryVO {
    private List<Integer> idList;

    public List<Integer> getIdList() {
        return idList;
    }

    public void setIdList(List<Integer> idList) {
        this.idList = idList;
    }
}

com.zze.mybatis.pojo.QueryVO

<?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.zze.mybatis.mapper.UserMapper">
    <select id="getByIdList" resultType="user" parameterType="queryvo">
        select * from user
        <where>
            <foreach collection="idList" open="id in (" close=")" separator="," item="id">
              #{id}
            </foreach>
        </where>
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.QueryVO;
import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getByIdList(QueryVO queryVO);
}

com.zze.mybatis.mapper.UserMapper

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.QueryVO;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

public class MyBatisTest {
    private UserMapper userMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void test() {
        QueryVO queryVO = new QueryVO();
        queryVO.setIdList(Arrays.asList(1, 2, 3));
        List<User> userList = userMapper.getByIdList(queryVO);
        userList.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select * from user WHERE id in ( ? , ? , ? )
        ==> Parameters: 1(Integer), 2(Integer), 3(Integer)
         */
    }
}

test

要注意的是 mybatis 不支持直接传入集合,但我们可以如上示例将它放在包装类中传入。

关联查询

一对一

新建与用户关联的订单表和 pojo,配置映射文件:

package com.zze.mybatis.pojo;

import java.util.Date;

public class Order {
    private Integer id;
    private Integer uId;
    private Double totalPrice;
    private Date createDate;
    /*
    Order 一对一关联 User
     */
    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getuId() {
        return uId;
    }

    public void setuId(Integer uId) {
        this.uId = uId;
    }

    public Double getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(Double totalPrice) {
        this.totalPrice = totalPrice;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public User getUser() {
        return user;
    }

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

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", uId=" + uId +
                ", TotalPrice=" + totalPrice +
                ", createDate=" + createDate +
                ", user=" + user +
                '}';
    }
}

com.zze.mybatis.pojo.Order

<?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.zze.mybatis.mapper.OrderMapper">
    <resultMap id="orderMap" type="order">
        <!--
        注意:
                在关联查询时,每个映射字段都需配置,不可省略。
        -->
        <id property="id" column="oid"/>
        <result property="uId" column="uid"/>
        <result property="totalPrice" column="totalPrice"/>
        <result property="createDate" column="createdate"/>
        <!--
        通过 association 配置一对一关系
        -->
        <association property="user" javaType="user">
            <id property="id" column="uid"/>
            <result property="name" column="name"/>
            <result property="birthday" column="birthday"/>
        </association>
    </resultMap>

    <select id="getAll" resultMap="orderMap">
      select o1.id oid,o1.uid,totalPrice,createdate,name,birthday from `order` o1 left join `user` u1 on o1.uid = u1.id;
    </select>
</mapper>

com/zze/mybatis/mapper/OrderMapper.xml

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.OrderMapper;
import com.zze.mybatis.pojo.Order;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class OrderTest {

    private OrderMapper orderMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        orderMapper = sqlSession.getMapper(OrderMapper.class);
    }

    @Test
    public void test() {
        List<Order> orderList = orderMapper.getAll();
        orderList.forEach(o -> System.out.println(o));

        /*
        ==>  Preparing: select o1.id oid,o1.uid,totalPrice,createdate,name,birthday from `order` o1 left join `user` u1 on o1.uid = u1.id;

        Order{id=1, uId=1, TotalPrice=324.0, createDate=Thu Mar 21 11:10:20 CST 2019, user=User{id=1, name='张三', birthday=Thu Jan 01 00:00:00 CST 1998}}
        Order{id=3, uId=1, TotalPrice=543.0, createDate=Mon Mar 18 11:11:05 CST 2019, user=User{id=1, name='张三', birthday=Thu Jan 01 00:00:00 CST 1998}}
        Order{id=2, uId=3, TotalPrice=23.0, createDate=Fri Mar 01 06:04:07 CST 2019, user=User{id=3, name='李四', birthday=Thu Jan 01 00:00:00 CST 1998}}
         */
    }
}

test

一对多

修改用户的 pojo 关联订单,配置映射文件:

package com.zze.mybatis.pojo;

import java.util.Date;
import java.util.List;

public class User {
    private Integer id;
    private String name;
    private Date birthday;

    /*
    User 一对多关联 Order
     */
    private List<Order> orders;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

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

    public List<Order> getOrders() {
        return orders;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

com.zze.mybatis.pojo.User

<?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.zze.mybatis.mapper.UserMapper">
    <resultMap id="userMap" type="user">
        <id property="id" column="uId"/>
        <result property="name" column="name"/>
        <result property="birthday" column="birthday"/>
        <!--
        使用 collection 标签建立一对多关系
            注意,这里使用的是 ofType,而一对一关联时使用的是 javaType
        -->
        <collection property="orders" ofType="order">
            <id property="id" column="oId"/>
            <result property="totalPrice" column="totalPrice"/>
            <result property="createDate" column="createDate"/>
            <result property="uId" column="uId"/>
        </collection>
    </resultMap>

    <select id="getAll" resultMap="userMap">
        select u1.id uId,o1.id oId,totalPrice,createdate,name,birthday from `user` u1 left join `order` o1 on u1.id=o1.uid;
    </select>
</mapper>

com/zze/mybatis/mapper/OrderMapper.xml

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class UserTest {
    private UserMapper userMapper;

    @Before
    public void init() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void test() {
        List<User> userList = userMapper.getAll();
        for (User user : userList) {
            System.out.println(user);
            System.out.println("--------> orders:" + user.getOrders());
        }

        /*
        ==>  Preparing: select u1.id uId,o1.id oId,totalPrice,createdate,name,birthday from `user` u1 left join `order` o1 on u1.id=o1.uid;
        <==      Total: 3
        User{id=1, name='张三', birthday=Thu Jan 01 00:00:00 CST 1998}
        --------> orders:[Order{id=1, uId=1, TotalPrice=324.0, createDate=Thu Mar 21 11:10:20 CST 2019, user=null}, Order{id=3, uId=1, TotalPrice=543.0, createDate=Mon Mar 18 11:11:05 CST 2019, user=null}]
        User{id=3, name='李四', birthday=Thu Jan 01 00:00:00 CST 1998}
        --------> orders:[Order{id=2, uId=3, TotalPrice=23.0, createDate=Fri Mar 01 06:04:07 CST 2019, user=null}]
         */
    }
}

test

MyBatis与Spring整合

整合思路

  1. SqlSessionFactory 对象应该交给 Spring 管理并作为单例存在。
  2. 传统 dao 的开发方式中,应该从 Spring 容器中获取 SqlSession 对象。
  3. Mapper 动态代理开发方式中,应该从 Spring 容器中直接获得 Mapper 对象。
  4. 数据库的连接及连接池、事务都交给 Spring 管理。

准备

1、创建一个 maven java 工程,引入相关依赖:

<?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.zze.mybatis</groupId>
    <artifactId>mybatis_spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>
        <!--mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <!--mybatis 整合 spring-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!--阿里巴巴数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.18</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

pom.xml

2、引入 mybatis 核心配置文件:

<?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>

</configuration>

config/SqlMapConfig.xml

3、引入 jdbc 连接信息属性文件:

jdbc.url=jdbc:mysql://192.168.208.192:3306/test?characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

config/jdbc.properties

4、引入 log4j 属性文件:

log4j.rootLogger = debug,stdout,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j.properties

5、引入 spring 核心配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!--读取属性文件-->
    <context:property-placeholder location="classpath:config/jdbc.properties"/>
    <!--连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!-- 基本属性 url、user、password -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="maxActive" value="20"/>
        <property name="initialSize" value="1"/>
        <property name="minIdle" value="1"/>
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    </bean>
    <!--配置 SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置核心配置文件路径-->
        <property name="configLocation" value="classpath:config/SqlMapConfig.xml"/>
        <!--配置别名扫描包-->
        <property name="typeAliasesPackage" value="com.zze.mybatis.pojo"/>
    </bean>
</beans>

config/applicationContext.xml

6、创建测试用 pojo 及其映射文件:

package com.zze.mybatis.pojo;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private String gender;
    private Date birthday;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getBirthday() {
        return birthday;
    }

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

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", birthday=" + birthday +
                ", address='" + address + '\'' +
                '}';
    }
}

com.zze.mybatis.pojo.User

<?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>
    <mappers>
        <mapper resource="config/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

config/mapper/UserMapper.xml

7、创建 dao 接口:

package com.zze.mybatis.dao;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserDao {
    List<User> getAll();
}

com.zze.mybatis.dao.UserDao

传统dao开发

1、在 mybatis 核心配置文件中引入映射文件:

<?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>
    <mappers>
        <mapper resource="config/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

config/SqlMapConfig.xml

2、编写 dao 接口实现类:

package com.zze.mybatis.dao.impl;

import com.zze.mybatis.dao.UserDao;
import com.zze.mybatis.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
    @Override
    public List<User> getAll() {
        SqlSession sqlSession = super.getSqlSession();
        List<User> userList = sqlSession.selectList("user.getAll");
        // 注意,这里 SqlSession 的实例的创建与销毁已经交给 Spring 管理,不用手动关闭,否则会异常
        return userList;
    }
}

com.zze.mybatis.dao.impl.UserDaoImpl

3、修改 Spring 配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!--读取属性文件-->
    <context:property-placeholder location="classpath:config/jdbc.properties"/>
    <!--连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!-- 基本属性 url、user、password -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="maxActive" value="20"/>
        <property name="initialSize" value="1"/>
        <property name="minIdle" value="1"/>
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    </bean>
    <!--配置 SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置核心配置文件路径-->
        <property name="configLocation" value="classpath:config/SqlMapConfig.xml"/>
        <!--配置别名扫描包-->
        <property name="typeAliasesPackage" value="com.zze.mybatis.pojo"/>
    </bean>

    <bean id="userDao" class="com.zze.mybatis.dao.impl.UserDaoImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

config/applicationContext.xml

4、测试:

package com.zze.mybatis.test;

import com.zze.mybatis.dao.UserDao;
import com.zze.mybatis.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class UserDaoTest {

    private ApplicationContext applicationContext;
    @Before
    public void init(){
        applicationContext = new ClassPathXmlApplicationContext("classpath:config/applicationContext.xml");
    }
    @Test
    public void test(){
        UserDao userDao = applicationContext.getBean(UserDao.class);
        List<User> userList = userDao.getAll();
        userList.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select id,name,gender,birthday,address from user;
         */
    }
}

com.zze.mybatis.test.UserDaoTest

动态代理开发

1、修改 UserDao 为 UserMapper:

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getAll();
}

com.zze.mybatis.mapper.UserMapper

2、将映射文件放入 mapper 同一目录,并指定 namespace 为 mapper 类全路径:

<?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.zze.mybatis.mapper.UserMapper">
    <select id="getAll" resultType="user">
        select id,name,gender,birthday,address from user;
    </select>
</mapper>

com/zze/mybatis/mapper/UserMapper.xml

3、修改 Spring 配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!--读取属性文件-->
    <context:property-placeholder location="classpath:config/jdbc.properties"/>
    <!--连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!-- 基本属性 url、user、password -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="maxActive" value="20"/>
        <property name="initialSize" value="1"/>
        <property name="minIdle" value="1"/>
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    </bean>
    <!--配置 SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置核心配置文件路径-->
        <property name="configLocation" value="classpath:config/SqlMapConfig.xml"/>
        <!--配置别名扫描包-->
        <property name="typeAliasesPackage" value="com.zze.mybatis.pojo"/>
    </bean>

    <!--动态代理配置方式一:配置单个接口-->
    <!--
    <bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
    <bean parent="baseMapper">
        <property name="mapperInterface" value="com.zze.mybatis.mapper.UserMapper"/>
    </bean>
    -->
    <!--动态代理配置方式二:配置 mapper 包扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zze.mybatis.mapper"/>
    </bean>
</beans>

config/applicationContext.xml

4、测试:

package com.zze.mybatis.test;

import com.zze.mybatis.dao.UserDao;
import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class UserMapperTest {

    private ApplicationContext applicationContext;
    @Before
    public void init(){
        applicationContext = new ClassPathXmlApplicationContext("classpath:config/applicationContext.xml");
    }
    @Test
    public void test(){
        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
        List<User> userList = userMapper.getAll();
        userList.forEach(u-> System.out.println(u));
        /*
        ==>  Preparing: select id,name,gender,birthday,address from user;
         */
    }
}

com.zze.mybatis.test.UserMapperTest

逆向工程

创建maven逆向工程

1、创建 maven java 工程,引入如下依赖:

<?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.zze</groupId>
    <artifactId>mybaits_generator</artifactId>
    <version>Lasted</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.6</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
</project>

pom.xml

2、引入逆向生成配置文件:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!-- 可以用于加载配置项或者配置文件,在整个配置文件中就可以使用${propertyKey}的方式来引用配置项
    resource:配置资源加载地址,使用resource,MBG从classpath开始找,比如com/myproject/generatorConfig.properties
    url:配置资源加载地质,使用URL的方式,比如file:///C:/myfolder/generatorConfig.properties.
    注意,两个属性只能选址一个;

    另外,如果使用了mybatis-generator-maven-plugin,那么在pom.xml中定义的properties都可以直接在generatorConfig.xml中使用
    <properties resource="" url="" />
    -->

    <!-- 在MBG工作的时候,需要额外加载的依赖包
       location属性指明加载jar/zip包的全路径
   <classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />
     -->

    <!--
        context:生成一组对象的环境
        id:必选,上下文id,用于在生成错误时提示
        defaultModelType:指定生成对象的样式
            1,conditional:类似hierarchical;
            2,flat:所有内容(主键,blob)等全部生成在一个对象中;
            3,hierarchical:主键生成一个XXKey对象(key class),Blob等单独生成一个对象,其他简单属性在一个对象中(record class)
        targetRuntime:
            1,MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample;
            2,MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample;
        introspectedColumnImpl:类全限定名,用于扩展MBG
    -->
    <context id="mybatisGenerator">
        <!--
            自动识别数据库关键字,默认false,如果设置为true,根据SqlReservedWords中定义的关键字列表;
            一般保留默认值,遇到数据库关键字(Java关键字),使用columnOverride覆盖
        -->
        <property name="autoDelimitKeywords" value="false"/>
        <!-- 生成的Java文件的编码 -->
        <property name="javaFileEncoding" value="UTF-8"/>
        <!-- 格式化java代码 -->
        <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
        <!-- 格式化XML代码 -->
        <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>

        <!-- beginningDelimiter和endingDelimiter:指明数据库的用于标记数据库对象名的符号,比如ORACLE就是双引号,MYSQL默认是`反引号; -->
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/test?
                                serverTimezone=CTT&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"
                        userId="root"
                        password="root">
        </jdbcConnection>

        <!-- java类型处理器
        用于处理DB中的类型到Java中的类型,默认使用JavaTypeResolverDefaultImpl;
        注意一点,默认会先尝试使用Integer,Long,Short等来对应DECIMAL和 NUMERIC数据类型;
        -->
        <javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
            <!--
                true:使用BigDecimal对应DECIMAL和 NUMERIC数据类型
                false:默认,
                    scale>0;length>18:使用BigDecimal;
                    scale=0;length[10,18]:使用Long;
                    scale=0;length[5,9]:使用Integer;
                    scale=0;length<5:使用Short;
             -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- java模型创建器,是必须要的元素
        负责:1,key类(见context的defaultModelType);2,java类;3,查询类
        targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
        targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
        -->
        <javaModelGenerator targetPackage="com.zze.mybatis.pojo"
                            targetProject="mybatis_spring/src/main/java">
            <!--  for MyBatis3/MyBatis3Simple
            自动为每一个生成的类创建一个构造方法,构造方法包含了所有的field;而不是使用setter;
            -->
            <property name="constructorBased" value="false"/>

            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="true"/>

            <!-- for MyBatis3 / MyBatis3Simple
                是否创建一个不可变的类,如果为true,
                那么MBG会创建一个没有setter方法的类,取而代之的是类似constructorBased的类
             -->
            <property name="immutable" value="false"/>

            <!-- 设置一个根对象,
                如果设置了这个根对象,那么生成的keyClass或者recordClass会继承这个类;在Table的rootClass属性中可以覆盖该选项
                注意:如果在key class或者record class中有root class相同的属性,MBG就不会重新生成这些属性了,包括:
                    1,属性名相同,类型相同,有相同的getter/setter方法;
             -->
            <!-- <property name="rootClass" value="com.zze.mybatis.pojo.BaseDomain"/>-->

            <!-- 设置是否在getter方法中,对String类型字段调用trim()方法 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成SQL map的XML文件生成器,
             注意,在Mybatis3之后,我们可以使用mapper.xml文件+Mapper接口(或者不用mapper接口),
                 或者只使用Mapper接口+Annotation,所以,如果 javaClientGenerator配置中配置了需要生成XML的话,这个元素就必须配置
             targetPackage/targetProject:同javaModelGenerator
        -->
        <sqlMapGenerator targetPackage="com.zze.mybatis.mapper"
                         targetProject="mybatis_spring/src/main/resources">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!-- 对于mybatis来说,即生成Mapper接口,注意,如果没有配置该元素,那么默认不会生成Mapper接口
            targetPackage/targetProject:同javaModelGenerator
            type:选择怎么生成mapper接口(在MyBatis3/MyBatis3Simple下):
                1,ANNOTATEDMAPPER:会生成使用Mapper接口+Annotation的方式创建(SQL生成在annotation中),不会生成对应的XML;
                2,MIXEDMAPPER:使用混合配置,会生成Mapper接口,并适当添加合适的Annotation,但是XML会生成在XML中;
                3,XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
            注意,如果context是MyBatis3Simple:只支持ANNOTATEDMAPPER和XMLMAPPER
        -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.zze.mybatis.mapper"
                             targetProject="mybatis_spring/src/main/java">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="true"/>

            <!-- 可以为所有生成的接口添加一个父接口,但是MBG只负责生成,不负责检查-->
            <!--<property name="rootInterface" value=""/>-->

        </javaClientGenerator>
        <!-- 选择一个table来生成相关文件,可以有一个或多个table,必须要有table元素
            选择的table会生成一下文件:
            1,SQL map文件
            2,生成一个主键类;
            3,除了BLOB和主键的其他字段的类;
            4,包含BLOB的类;
            5,一个用户生成动态查询的条件类(selectByExample, deleteByExample),可选;
            6,Mapper接口(可选)

            tableName(必要):要生成对象的表名;
            注意:大小写敏感问题。正常情况下,MBG会自动的去识别数据库标识符的大小写敏感度,在一般情况下,MBG会
                根据设置的schema,catalog或tablename去查询数据表,按照下面的流程:
                1,如果schema,catalog或tablename中有空格,那么设置的是什么格式,就精确的使用指定的大小写格式去查询;
                2,否则,如果数据库的标识符使用大写的,那么MBG自动把表名变成大写再查找;
                3,否则,如果数据库的标识符使用小写的,那么MBG自动把表名变成小写再查找;
                4,否则,使用指定的大小写格式查询;
            另外的,如果在创建表的时候,使用的""把数据库对象规定大小写,就算数据库标识符是使用的大写,在这种情况下也会使用给定的大小写来创建表名;
            这个时候,请设置delimitIdentifiers="true"即可保留大小写格式;

            可选:
            1,schema:数据库的schema;
            2,catalog:数据库的catalog;
            3,alias:为数据表设置的别名,如果设置了alias,那么生成的所有的SELECT SQL语句中,列名会变成:alias_actualColumnName
            4,domainObjectName:生成的domain类的名字,如果不设置,直接使用表名作为domain类的名字;可以设置为somepck.domainName,那么会自动把domainName类再放到somepck包里面;
            5,enableInsert(默认true):指定是否生成insert语句;
            6,enableSelectByPrimaryKey(默认true):指定是否生成按照主键查询对象的语句(就是getById或get);
            7,enableSelectByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询语句;
            8,enableUpdateByPrimaryKey(默认true):指定是否生成按照主键修改对象的语句(即update);
            9,enableDeleteByPrimaryKey(默认true):指定是否生成按照主键删除对象的语句(即delete);
            10,enableDeleteByExample(默认true):MyBatis3Simple为false,指定是否生成动态删除语句;
            11,enableCountByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询总条数语句(用于分页的总条数查询);
            12,enableUpdateByExample(默认true):MyBatis3Simple为false,指定是否生成动态修改语句(只修改对象中不为空的属性);
            13,modelType:参考context元素的defaultModelType,相当于覆盖;
            14,delimitIdentifiers:参考tableName的解释,注意,默认的delimitIdentifiers是双引号,如果类似MYSQL这样的数据库,使用的是`(反引号,那么还需要设置context的beginningDelimiter和endingDelimiter属性)
            15,delimitAllColumns:设置是否所有生成的SQL中的列名都使用标识符引起来。默认为false,delimitIdentifiers参考context的属性

            注意,table里面很多参数都是对javaModelGenerator,context等元素的默认属性的一个复写;
         -->
        <table tableName="user" domainObjectName="User">
            <!-- 参考 javaModelGenerator 的 constructorBased属性-->
            <property name="constructorBased" value="false"/>

            <!-- 默认为false,如果设置为true,在生成的SQL中,table名字不会加上catalog或schema; -->
            <property name="ignoreQualifiersAtRuntime" value="false"/>

            <!-- 参考 javaModelGenerator 的 immutable 属性 -->
            <property name="immutable" value="false"/>
            <!-- 指定是否只生成domain类,如果设置为true,只生成domain类,如果还配置了sqlMapGenerator,那么在mapper XML文件中,只生成resultMap元素 -->
            <property name="modelOnly" value="false"/>

            <!-- 参考 javaModelGenerator 的 rootClass 属性
            <property name="rootClass" value=""/>
             -->

            <!-- 参考javaClientGenerator 的  rootInterface 属性
            <property name="rootInterface" value=""/>
            -->

            <!-- 如果设置了runtimeCatalog,那么在生成的SQL中,使用该指定的catalog,而不是table元素上的catalog
            <property name="runtimeCatalog" value=""/>
            -->

            <!-- 如果设置了runtimeSchema,那么在生成的SQL中,使用该指定的schema,而不是table元素上的schema
            <property name="runtimeSchema" value=""/>
            -->

            <!-- 如果设置了runtimeTableName,那么在生成的SQL中,使用该指定的tablename,而不是table元素上的tablename
            <property name="runtimeTableName" value=""/>
            -->

            <!-- 注意,该属性只针对MyBatis3Simple有用;
                如果选择的runtime是MyBatis3Simple,那么会生成一个SelectAll方法,如果指定了selectAllOrderByClause,那么会在该SQL中添加指定的这个order条件;
             -->
            <property name="selectAllOrderByClause" value="age desc,username asc"/>

            <!-- 如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法,比如BORN_DATE,生成的属性名字就是BORN_DATE,而不会是bornDate -->
            <property name="useActualColumnNames" value="false"/>

            <!-- generatedKey用于生成生成主键的方法,
                如果设置了该元素,MBG会在生成的<insert>元素中生成一条正确的<selectKey>元素,该元素可选
                column:主键的列名;
                sqlStatement:要生成的selectKey语句,有以下可选项:
                    Cloudscape:相当于selectKey的SQL为: VALUES IDENTITY_VAL_LOCAL()
                    DB2       :相当于selectKey的SQL为: VALUES IDENTITY_VAL_LOCAL()
                    DB2_MF    :相当于selectKey的SQL为:SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
                    Derby     :相当于selectKey的SQL为:VALUES IDENTITY_VAL_LOCAL()
                    HSQLDB    :相当于selectKey的SQL为:CALL IDENTITY()
                    Informix  :相当于selectKey的SQL为:select dbinfo('sqlca.sqlerrd1') from systables where tabid=1
                    MySql     :相当于selectKey的SQL为:SELECT LAST_INSERT_ID()
                    SqlServer :相当于selectKey的SQL为:SELECT SCOPE_IDENTITY()
                    SYBASE    :相当于selectKey的SQL为:SELECT @@IDENTITY
                    JDBC      :相当于在生成的insert元素上添加useGeneratedKeys="true"和keyProperty属性
            <generatedKey column="" sqlStatement=""/>
             -->

            <!--
                该元素会在根据表中列名计算对象属性名之前先重命名列名,非常适合用于表中的列都有公用的前缀字符串的时候,
                比如列名为:CUST_ID,CUST_NAME,CUST_EMAIL,CUST_ADDRESS等;
                那么就可以设置searchString为"^CUST_",并使用空白替换,那么生成的Customer对象中的属性名称就不是
                custId,custName等,而是先被替换为ID,NAME,EMAIL,然后变成属性:id,name,email;

                注意,MBG是使用java.util.regex.Matcher.replaceAll来替换searchString和replaceString的,
                如果使用了columnOverride元素,该属性无效;

            <columnRenamingRule searchString="" replaceString=""/>
             -->

            <!-- 用来修改表中某个列的属性,MBG会使用修改后的列来生成domain的属性;
                column:要重新设置的列名;
                注意,一个table元素中可以有多个columnOverride元素
                property : 使用property属性来指定列要生成的属性名称
                javaType : 用于指定生成的domain的属性类型,使用类型的全限定名
                jdbcType : 用于指定该列的JDBC类型
                typeHandler : 用于指定该列使用到的TypeHandler,如果要指定,配置类型处理器的全限定名
                delimitedColumnName : 参考table元素的delimitAllColumns配置,默认为false
                注意,mybatis中,不会生成到mybatis-config.xml中的typeHandler
                只会生成类似:where id = #{id,jdbcType=BIGINT,typeHandler=com._520it.mybatis.MyTypeHandler}的参数描述
             -->
            <columnOverride column="name" property="name"/>

            <!-- ignoreColumn设置一个MGB忽略的列,如果设置了改列,那么在生成的domain中,生成的SQL中,都不会有该列出现
               column:指定要忽略的列的名字;
               delimitedColumnName:参考table元素的delimitAllColumns配置,默认为false

               注意,一个table元素中可以有多个ignoreColumn元素
            <ignoreColumn column="deptId" delimitedColumnName=""/>
            -->
        </table>

    </context>
</generatorConfiguration>

generatorConfig.xml

3、引入日志文件:

log4j.rootLogger = debug,stdout

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j.properties

4、引入可执行 java 类:

import org.apache.ibatis.io.Resources;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all")
public class Generator {
    public void generator() throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        /**指向逆向工程配置文件*/
        File configFile = Resources.getResourceAsFile("generatorConfig.xml");
        ConfigurationParser parser = new ConfigurationParser(warnings);
        Configuration config = parser.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                callback, warnings);
        myBatisGenerator.generate(null);
    }

    public static void main(String[] args) throws Exception {
        try {
            Generator generatorSqlmap = new Generator();
            generatorSqlmap.generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Generator

5、在‘generatorConfig.xml’中完成相关配置,执行 Generator 即可。

使用

package com.zze.mybaits.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.pojo.User;
import com.zze.mybatis.pojo.UserExample;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

public class UserMapperTest {

    private ApplicationContext applicationContext;
    private UserMapper userMapper;

    @Before
    public void init() {
        applicationContext = new ClassPathXmlApplicationContext("classpath:config/applicationContext.xml");
        userMapper = applicationContext.getBean(UserMapper.class);
    }

    @Test
    public void testSelectByPrimaryKey() {
        User user = userMapper.selectByPrimaryKey(2);
        System.out.println(user);
        /*
        ==>  Preparing: select id, name, gender, birthday, address from user where id = ?
        ==>  Parameters: 2(Integer)
         */
    }

    /**
     * 指定条件查询返回列表
     */
    @Test
    public void testSelectByExample() {
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andNameLike("%郭%");
        List<User> userList = userMapper.selectByExample(userExample);
        userList.forEach(u -> System.out.println(u));
        /*
        ==>  Preparing: select id, name, gender, birthday, address from user WHERE ( name like ? )
        ==>  Parameters: %郭%(String)
         */
    }

    /**
     * 新增非空字段
     */
    @Test
    public void testInsertSelective() throws ParseException {
        userMapper.insertSelective(new User(null, "郭德纲", "男", new SimpleDateFormat("yyyy-MM-dd").parse("1997-1-1"), null));
        /*
        ==>  Preparing: insert into user ( name, gender, birthday ) values ( ?, ?, ? )
        ==>  Parameters: 郭德纲(String), 男(String), 1997-01-01(Date)
         */
    }

    /**
     * 新增全部
     */
    @Test
    public void testInsert() throws ParseException {
        userMapper.insert(new User(null, "郭德纲", "男", new SimpleDateFormat("yyyy-MM-dd").parse("1997-1-1"), null));
        /*
        ==>  Preparing: insert into user (id, name, gender, birthday, address) values (?, ?, ?, ?, ?)
        ==>  Parameters: null, 郭德纲(String), 男(String), 1997-01-01(Date), null
         */
    }

    /**
     * 修改非空字段
     */
    @Test
    public void testUpdateByPrimaryKeySelective() {
        userMapper.updateByPrimaryKeySelective(new User(1, "周华健", "男", null, null));
        /*
        ==>  Preparing: update user SET name = ?, gender = ? where id = ?
        ==>  Parameters: 周华健(String), 男(String), 1(Integer)
         */
    }

    /**
     * 修改全部
     */
    @Test
    public void testUpdateByPrimaryKey() {
        userMapper.updateByPrimaryKey(new User(1, "周华健", "男", null, null));
        /*
        ==>  Preparing: update user set name = ?, gender = ?, birthday = ?, address = ? where id = ?
        ==>  Parameters: 周华健(String), 男(String), null, null, 1(Integer)
         */
    }

    /**
     * 指定条件批量删除
     */
    @Test
    public void testDeleteByExample() {
        UserExample userExample = new UserExample();
        // 删除名字中包含郭字的记录
        userExample.createCriteria().andNameLike("%郭%");
        userMapper.deleteByExample(userExample);
        /*
        ==>  Preparing: delete from user WHERE ( name like ? )
        ==>  Parameters: %郭%(String)
         */
    }

    /**
     * 根据主键删除
     */
    @Test
    public void testDeleteByPrimaryKey() {
        userMapper.deleteByPrimaryKey(10);
        /*
        ==>  Preparing: delete from user where id = ?
        ==>  Parameters: 10(Integer)
         */
    }

    /**
     * 条件查询记录条数
     */
    @Test
    public void testCountByExample() {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andNameLike("%周%");
        long l = userMapper.countByExample(userExample);
        System.out.println(l);
        /*
        ==>  Preparing: select count(*) from user WHERE ( name like ? )
        ==>  Parameters: %周%(String)
         */
    }
}
05-11 11:03