欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis框架学习-2

程序员文章站 2022-05-24 20:21:50
...

MyBatis框架安排

2. 第二天:

1. MyBatis的增删改查操作(操作配置文件SqlMapConfig.xml)

  1. 在SqlMapConfig.xml中向数据库中增加条目

    <!-- 插入数据 -->
    <!-- parameterType="com.liuzeyu.domin.User"参数类型,通过反射为#{username}...赋值-->
    <insert id="save" parameterType="com.liuzeyu.domin.User">
        <!-- 插入数后返回id,keyProperty="id"对应实体类属性,keyColumn="id"对应数据库列名,AFTER:操作最后执行-->
        <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int">
        <!-- SELECT last_insert_id()  返回刚刚插入的数据id-- >
            SELECT last_insert_id() 
        </selectKey>
        insert into user (username,birthday,sex,address)VALUES (#{username},#{birthday},#{sex},#{address})
    </insert>
    
  2. 在SqlMapConfig.xml中向数据库中删除条目

    <!-- 根据id删除-->
    <delete id="delete" parameterType="int">
        delete from user where id=#{uid}
    </delete>
    
  3. 在SqlMapConfig.xml向数据库中修改条目

    <!-- 更新数据 -->
    <update id="update" parameterType="com.liuzeyu.domin.User">
        UPDATE user SET username=#{username},birthday=#{birthday},address=#{address},sex=#{sex} where id=#{id}
    </update>
    
  4. 在SqlMapConfig.xml向数据库中查询条目

        <!-- 根据id查找一个 -->
        <select id="findById" resultType="com.liuzeyu.domin.User" parameterType="int">
            select * from user where id=#{uid}
        </select>
        <!-- 根据name查找集合 -->
        <select id="findByName" resultType="com.liuzeyu.domin.User" parameterType="string">
              select * from user where username like #{string}
        <!-- select * from user where username like '%${value}%' -->
      </select>
      <!-- 查询总记录数-->
        <select id="findTotal" resultType="int">
            SELECT count(*) FROM USER
        </select>
    

测试类:

```
package com.liuzeyu.test;

import com.liuzeyu.dao.IUserDao;
import com.liuzeyu.domin.User;
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 org.junit.After;
import org.junit.Before;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class Test {
    private InputStream is = null;
    private IUserDao userDao = null;
    private  SqlSession session = null;
    /**
     * 初始化
     * @throws IOException
     */
    @Before  //测试开始前执行
    public void init() throws IOException {
        //1.解析xml配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.构建工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //3.工厂生产SqlSession对象
        session = factory.openSession();
        //4.创建代理Dao的对象
        userDao = session.getMapper(IUserDao.class);
    }
    @After //测试结束后执行
    public void destory(){
        session.commit();
        //7.释放资源
        if( session != null){
            session.close();
        }
        if( is != null){
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @org.junit.Test
    public void testSelect() throws IOException {
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //6.遍历对象
        for (User user : users) {
            System.out.println(user);
        }
    }
    @org.junit.Test
    public void testSave() throws IOException {
        User user = new User();
        user.setUsername("liuzeyu");
        user.setBirthday(new Date());
        user.setAddress("莆田");
        user.setSex("男");
        System.out.println("保存前:"+user);
        userDao.save(user);
        System.out.println("保存后:"+user);
    }
    @org.junit.Test
    public void testUpdate() throws IOException {
        User user = new User();
        user.setId(48);
        user.setUsername("duyangting");
        user.setBirthday(new Date());
        user.setAddress("厦门");
        user.setSex("女");
        userDao.update(user);
    }
    @org.junit.Test
    public void testDelete() throws IOException {
        userDao.delete(46);
    }
    @org.junit.Test
    public void testFindOne() throws IOException {
        User user = userDao.findById(42);
        System.out.println(user);
    }

    @org.junit.Test
    public void testFindOneByName() throws IOException {
           List<User> users = userDao.findByName("%王%");//使用的是PreparedStatement的查询方式,Preparing: select * from user where username like ?
//        List<User> users = userDao.findByName("王"); //使用的是拼接字符串的查询方式,Preparing: select * from user where username like '%王%'
        for (User user : users) {
            System.out.println(user);
        }
    }
    @org.junit.Test
    public void testFindTotal() throws IOException {
        int total = userDao.findTotal();
        System.out.println(total);
    }
}
```

2. 多个对象组成一个查询条件

  1. 将user 对象使用类QueryStringVo包装
    /**
     * 将查询条件封装到一个类中
     */
    public class QueryStringVo {
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    }
    
  2. 在SqlMapConfig.xml向数据库中查询条件
    </select>
    <!-- 根据queryStringVo查询-->
    <select id="findByVo" resultType="com.liuzeyu.domin.User" parameterType="com.liuzeyu.vo.QueryStringVo">
        select * from user where username like #{user.username}
        <!-- select * from user where username like '%${value}%' -->
    </select>
  1. 测试函数(结果与模糊查询一致)

       @org.junit.Test
        public void testFindOneByVo() throws IOException {
            QueryStringVo vo = new QueryStringVo();
            User user = new User();
            user.setUsername("%王%");
            vo.setUser(user);
            List<User> users = userDao.findByVo(vo);//使用的是PreparedStatement的查询方式,Preparing: select * from user where username like ?
    
            for (User u : users) {
                System.out.println(u);
            }
        }
    

3. OGNL表达式介绍

OGNL :Object Graphic Navigation Lanuage (对象图导航语言)
它是通过对象取值方法来获取数据的,在写法上把类似JavaBean的get方法给删掉了。

类中的写法 user.getUsername
OGNL表达式:user.username

例如上面的

<insert id="save" parameterType="com.liuzeyu.domin.User">
    insert into user (username,birthday,sex,address)VALUES (#{username},#{birthday},#{sex},#{address})
</insert>

由于parameterType属性已经提供了类的路径,则要获取values的username需要之需要写User类的属性即可#{username},否则需要写user.username
类似于:

 <!-- 根据queryStringVo查询-->
 <select id="findByVo" resultType="com.liuzeyu.domin.User" parameterType="com.liuzeyu.vo.QueryStringVo">
     select * from user where username like #{user.username}
     <!-- select * from user where username like '%${value}%' -->
 </select>

4. 数据库表字段和实体类属性不一致问题

解决方法有两个:
方法一:通过对发送的sql语句字段名取别名来处理

 <!-- 打印user表数据 -->
 <select id="findAll" resultType="com.liuzeyu.domin.User">
     <!-- 取别名来和实体类产生关系 -->
     <!--SELECT id as userId,username as userName,address as userAddress,birthday as userBirthday ,sex as userSex from user -->
 </select>

其中userId,userName,userAddress,userBirthday ,userSex 是实体类的属性。
对应的数据库列名:id,username,address,birthday,sex
这样查询出来的结果的字段名就是userId,userName,userAddress,userBirthday ,userSex ,此时就与实体类一一对应了。

方法二:通过配置文件来实现:

 <!-- 配置查询的列名和实体类直接的对应关系-->
 <resultMap id="userMap" type="com.liuzeyu.domin.User">
     <!-- 主键id对应,property="userId"实体类属性, column="id"数据库列字段名-->
     <id property="userId" column="id"/>
     <!-- 非主键字段的对应关系-->
     <result property="userName" column="username"/>
     <result property="userAddress" column="address"/>
     <result property="userBirthday" column="birthday"/>
     <result property="userSex" column="sex"/>
 </resultMap>

在操作数据库的标签内添加resultMap属性引用即可,如:

    <!-- 打印user表数据 -->
    <select id="findAll" resultType="com.liuzeyu.domin.User" resultMap="userMap">
         SELECT * from USER
    </select>

方法一比方法二的执行效率更高,但是方法二比方法一开发效率更高,就是说当项目比较大时,使用方法二会提高开发效率。

5. 优化主配置文件

  1. 引用外部连接数据库的连接信息
    在主配置文件下< configuration >标签内部添加properties 的resource配置或url配置引用外部配置文件
    <!-- 配置标签内部的属性连接数据库的信息,可以通过引用外部资源文件-->
    <!--1. resource的配置方式-->
	    <!--<properties resource="jdbcConfig.properties">-->
	    <!--</properties>-->
    <!--2. url的配置方式-->
        <!--
        url 与 uri的区别
        url:uniform resource locator 统一资源定位  唯一标识一个资源的位置
            写法:
            协议://主机:端口/uri
            http://localhost:80/servlet/index
        uri:uniform resource  Identifier 统一资源标识  在应用中唯一定位一个资源
        -->
	    <properties url="file:\\\C:\Users\lzy\IdeaProjects\day02_mybatis_modify\src\main\resources\jdbcConfig.properties">
	
	    </properties>

MyBatis框架学习-2

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis
jdbc.username=root
jdbc.password=809080

之后再JDBC的连接池里面以$获取实际配置文件中的值

<!-- 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>
  1. 为标签属性取别名
    取完别名后,可以再映射配置文件中直接使用
    <!--自定义为配置文件取别名-->
    <typeAliases>
        <!--<typeAlias type="com.liuzeyu.domin.User" alias="user"/>-->
        <package name="com.liuzeyu.domin"/>
    </typeAliases>

使用typeAlias 标签去别名和package有一个区别?
typeAlias 指定type对象后,alias是别名,并且再映射配置文件中使用它可以不区分大小写,如:
MyBatis框架学习-2
package标签是指定取别名的包,当指定后,该包下所有的实体类都会被指定别名,并且类名就是别名,不再区分大小写。

  1. 简化主配置的映射接口配置

        <mappers>
            <!--<mapper resource="com/liuzeyu/dao/IUserDao.xml"></mapper>-->
            <package name="com.liuzeyu.dao"></package>
        </mappers>
    

    上面这种配置有一个好处是,再package标签下指定dao接口所在的包,就可以不用再写mapper以及class和resource属性了,它可以直接找到映射配置文件