11-17 程宗武

11-17 Mybatis01

1.Mybatis概述

mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc ,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql并将结果映射为 java 对象并返回。

2.搭建 Mybatis 开发环境

2.1 使用maven构建

2.1.1 项目的层级目录

2.1.2在 pom.xml 文件中添加 Mybatis3.4.5 的依赖


<!-- Mybatis 依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
    <scope>runtime</scope>
</dependency>

2.1.3 编写持久层接口与映射的xml文件

1.持久层接口
public interface UserDao {
     List<User> getUserList();
}
2.映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatisTest.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.UserDao"> -->与持久层接口的包名一一对应
    <select id="getUserList" resultType="pojo.User"> -->id为方法名
       select * from userinfo
    </select>
</mapper>

2.1.4 编写config.xml文件(配置数据库连接信息和映射位置等)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatisTest.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.66.128/mybatis?serverTimezone=GMT"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        <mapper resource="dao/UserMapper.xml"/>-->
        <mapper resource="dao/UserMapper.xml"/>
    </mappers>
</configuration>

2.1.5 编写测试类

@Test
    public void test() {
        try {
            //获取配置信息的流文件
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            //得到sqlSessionFactory工厂对象
            SqlSessionFactory sqlSessionFactory = new                         SqlSessionFactoryBuilder().build(in);
            //得到SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //使用sqlSession创建代理对象
            UserDao dao = sqlSession.getMapper(UserDao.class);
            //使用代理对象执行方法
            List<User> list = dao.getUserList();
            for (User model : list) {
                System.out.println(model);
            }
            sqlSession.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3.MyBatis源码分析

4. 基于代理 Dao 实现 CRUD 操作

项目的目录结构

4.1添加log4j记录执行日志(resource目录下创建log4j.properties文件)

#日志级别为debug
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=%d{ABSOLUTE} %5p %c{1}:%L -%m%n
#写文件
#log4j.appender.file=org.apache.log4j.RollingFileAppender
#log4j.appender.file.MaxFileSize=1MB
#log4j.appender.file.MaxBackupIndex=1024
#log4j.appender.file.File=c\:/eshop.html
#log4j.appender.file.layout=org.apache.log4j.HTMLLayout
#log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss}
[%c]-[%-5p] %m%n%n

4.1 查询

注:mybatis默认自动提交事务是出于关闭状态的,因此,我们在实现增删改操作时一定要手动提交事务,否则操作将会失败,查询操作可不用提交。

4.1.1查询单个(根据ID查询)
//接口中定义方法:根据id查找user
User findById(String id);
//映射的配置文件中的配置(UserMapper.xml)
<select id="findById" resultType="pojo.User" parameterType="String">
    select * from userinfo WHERE id = #{id}
</select>
//测试类
 @Test
 public void findById() {
    User user = mapper.findById("001");
    System.out.println(user);//User(id=001, username=admin, password=123456)
}
4.1.2 查询多个(返回一个集合)
//查询所有
List<User> getUserList();   
//映射的配置文件中的配置(UserMapper.xml)
<select id="getUserList" resultType="pojo.User">
       select * from userinfo
</select>
//测试类
@Test
public void getUserList() {
List<User> userList = mapper.getUserList();
        for (User u :
                userList) {
            System.out.println(u);
        }
    }

4.1 增加

//添加用户
int saveUser(User user);
//映射的配置文件中的配置(UserMapper.xml)
<insert id="saveUser" parameterType="pojo.User">
    insert into
    userinfo(id,username,password,name,gender,birthday,phone,email)
    values(#{id},#{username},#{password},#{name},#{gender},#{birthday},#{phone},#{email})
</insert>
  //此处使用了ognl 表达式,应为我门设置了参数类型为User类型,因此#{username}相当于调用了User 的      getUsername()方法来获取username的值
//测试
  @Test
  public void saveUser() {
        User user = new User();
        user.setId("11");
        user.setUsername("aaa");
        user.setPassword("123123");
        user.setName("张三丰");
        user.setGender(1);
        user.setBirthday(new Date());
        user.setPhone("138xxxxxxxx");
        user.setEmail("123@qq.com");
        SqlSession sqlSession = SqlSessionUtil.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.saveUser(user);
        sqlSession.commit();//此处一定要记得提交事务,否则添加失败(事务回滚)
        List<User> userList = mapper.getUserList();
        for (User model : userList) {
            System.out.println(model);
        }
   }

4.1.1返回新增用户的id

//1.主键必须自增
//根据用户名存储用户
int saveUserByName(User user);
//映射的配置文件中的配置(UserMapper.xml)
<insert id="saveUserByName" parameterType="pojo.UserTest" useGeneratedKeys="true"       keyProperty="id">
    insert into usertest(name) values(#{name})
</insert>
//测试
@Test
public void saveUserByName() {
    User user = new User();
    user.setName("善逸");
    int i = mapper.saveUserByName(user);
    sqlSession.commit();
    System.out.print(user.getId());//12
 }
//2.主键可以不自增(插入之后查询)
<insert id="saveUserTest1"parameterType="com.itlaobing.model.UserInfoModel">
    <selectKey resultType ="String" order = "AFTER" keyProperty = "id" >
        select last_insert_id();
    </selectKey>
    insert into userinfo(name) values(#{name})
</insert>
//order指在插入之后查询id并返回
//2.主键可以不自增(插入之前设置)
 <insert id="saveUserByName" parameterType="pojo.User">
      <selectKey resultType="String" order="BEFORE" keyProperty="id">
            select uuid() as id;
      </selectKey>
   insert into userinfo(id,name) values(#{id},#{name})
</insert>
 //在插入之前,先从数据库中查询出一个uuid并设置到插入user的id字段上,并将设置之后的结果插入,之后返回的id就是之前从数据库里获取的那个uuid

4.2修改

//更新用户
int updateUser(User user);
 <!--    更新用户-->
 <update id="updateUser" parameterType="pojo.User">
     UPDATE userinfo SET name = #{name} WHERE id = #{id}
</update>
 //测试
//更新用户
@Test
public void updateUser() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user = mapper.findById("001");
        user.setName("炭治郎");
        mapper.updateUser(user);
        sqlSession.commit();
  }

4.3删除

//删除用户
int deleteUser(String id);
<!--    删除用户-->
<delete id="deleteUser" parameterType="String">
        DELETE FROM userinfo WHERE id = #{id}
</delete>
 //测试
 //删除用户
@Test
 public void deleteUser() {
        mapper.deleteUser("001");
        sqlSession.commit();
 }

5.基于代理 Dao实现高级查询

5.1模糊查询

//1.根据用户名模糊查询(修改传入参数)
List<User> findUserByName(String username);
<!--    根据用户名模糊查询用户-->
<select id="findUserByName" parameterType="String" resultType="pojo.User">
        SELECT * FROM userinfo WHERE username like '#{username}'
</select>
    //用户模糊查询
    @Test
    public void findUserByName() {
        List<User> list = mapper.findUserByName("%a%");
    //此处我们是将一个整体的参数传入到SQL语句的占位符处,当sql语句编译过后就会变成
    //Preparing: SELECT * FROM userinfo WHERE username like ?
    //参数为:Parameters: %a%(String)这个参数将会在SQL执行过程中进行赋值
        for (User u :
                list) {
            System.out.println(u);
        }
    }
//2.根据用户名模糊查询(修改UserMapper.xml中的SQL语句)
<select id="findUserByName" parameterType="String" resultType="pojo.User">
        SELECT * FROM userinfo WHERE username like '%${value}%'
        //注:此处占位符必须写成value,这种写法是固定的。
 </select>
//测试类中传入的参数为
List<User> list = mapper.findUserByName("a");
//此处在sql编译过程中就会把参数a赋值给value,此时的SQL语句编译过后就会变成
//Preparing: SELECT * FROM userinfo WHERE username like '%a%' 
//而参数已经赋值了 Parameters: 

5.2聚合函数查询

//聚合函数查询
int findTotal();
 <!--    查询数据库表中的总记录条数-->
 <select id="findTotal" resultType="int">
      SELECT COUNT(*) FROM userinfo
 </select>
//聚合函数查询数据库中的总记录条数
@Test
public void findTotal() {
     int total = mapper.findTotal();
     System.out.println(total);//3
 }

6.Mybatis参数探究

我门在使用parameterType设置参数时,为什么自己定义的参数必须要写全限定类名,例resultType="pojo.User"
而基本数据类型和String等就不需要写全限定类名,是因为Mybatis在加载时就把常用的数据类型注册了别名,我们在传入参数时,自动根据别名去找到全限定类名

6.1.传递包装对象

//1.vo类
@Data
public class QueryVo {
    private User user;
}
//2.持久层接口
//根据QueryVo中的属性查询用户
List<User> findByVo(QueryVo vo);
//3.映射文件
<select id="findByVo" resultType="pojo.User" parameterType="vojo.QueryVo">
      SELECT * FROM  userinfo WHERE username like #{user.username}
    //这里调用了vo对象的getUser方法返回了一个User然后调用了user对象的getusername方法获取到了值
</select>
//4.测试
@Test
public void findByVo() {
    QueryVo vo = new QueryVo();
    User user = new User();
    user.setUsername("%a%");
    vo.setUser(user);
    List<User> list = mapper.findByVo(vo);
    for (User u :
         list) {
        System.out.println(u);
    }
}

6.2resultMap 结果类型

resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。例如,如果我们实体类的属性设置的是createDate,而数据库中对应的列名是create_date,此时我们是获取不到数据库中的这一列的值的,因此,我们要使用resultMap 属性指定引用即可

//1.定义resultMap
<resultMap id="userMap" type="pojo.User">
    <id column="id" property="id"/>
    <result column="create_date" property="createDate"/>
    <result column="create_date" property="createDate"/>
</resultMap>
//2.映射
<select id="getUserList" resultMap="userMap">
       select * from userinfo
</select>
//3.测试
 @Test
public void getUserList() {
List<User> userList = mapper.getUserList();
    for (User u :
    userList) {
    System.out.println(u);//这里会查询出来所有字段
    }
}

7.SqlMapConfig.xml配置文件

7.1 SqlMapConfig.xml 中配置的内容和顺序

-properties(属性)
    --property
-settings(全局配置参数)
    --setting
-typeAliases(类型别名)
    --typeAliase
    --package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
    --environment(环境子属性对象)
        ---transactionManager(事务管理)
        ---dataSource(数据源)
-mappers(映射器)
    --mapper
    --package

7.2 properties的配置方式

<!--在SqlMapConfig.xml中配置-->
<properties>
    <property name="driver" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://192.168.66.128/mybatis?serverTimezone=GMT"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</properties>
<!--resources目录下定义 db.properties 文件-->

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.66.128/mybatis?serverTimezone=GMT
jdbc.username=root
jdbc.password=123456

<!--此时SqlMapConfig.xml中的配置可修改为-->
<configuration>
    <properties resource="db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
               <!-- <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.66.128/mybatis?serverTimezone=GMT"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        <mapper resource="dao/UserMapper.xml"/>-->
        <mapper resource="dao/UserMapper.xml"/>
    </mappers>
</configuration>

标签

评论

this is is footer