MyBaties学习:XML配置

一、XML方式

        MyBatis 的真正强大之处在于它的映射语句,这也是它的魔力所在。由于它的映射语句异常强大,映射器的XML 文件就显得相对简单。如果将其与具有相同功能的JDBC 代码进行对比, 立刻就会发现,使用这种方法节省了将近95%的代码量。 MyBatis 就是针对SQL构建的,并且比普通的方法做的更好

        MyBatis 3.0 的一个最大变化,就是支持使用接口来调用方法。MyBatis 使用Java 的动态代理可以直接通过接口来调用相应的方法不需要提供接口的实现类,更不需要在实现类中使用 SqlSession以通过命名空间间接调用。

二、xml示例:

2.1 创建数据库

创建如下的数据库,并插入数据:

CREATE TABLE `sys_user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户 ID',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `user_password` varchar(50) DEFAULT NULL COMMENT '密码',
  `user_email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `user_info` text COMMENT '简介',
  `head_img` blob COMMENT '头像',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户农';

 2.2 创建实体类

创建对应sys_user数据表的实体类:

public class SysUser {
    private Long id;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String userPassword;
    /**
     * 邮箱
     */
    private String userEmail;
    /**
     * 简介
     */
    private String userInfo;
    /**
     * 头像
     */
    private byte[] headImg;
    /**
     * 创建时间
     */
    private Date createTime;

    public Long getId() {
        return id;
    }

    public String getUserName() {
        return userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public String getUserInfo() {
        return userInfo;
    }

    public byte[] getHeadImg() {
        return headImg;
    }

    public Date getCreateTime() {
        return createTime;
    }

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

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

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public void setUserInfo(String userInfo) {
        this.userInfo = userInfo;
    }

    public void setHeadImg(byte[] headImg) {
        this.headImg = headImg;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

        对于 SysUser 实体类,在后面使用这些对象的时候,可以通过resultMap 对数据库的列和类的宇段配置映射关系

2.3 创建UserMapper.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.wyf.mybaties.mapper.UserMapper">
	<resultMap id="userMap" type="com.wyf.mybaties.model.SysUser">
		<id property="id" column="id"/>
		<result property="userName" column="user_name"/>
		<result property="userPassword" column="user_password"/>
		<result property="userEmail" column="user_email"/>
		<result property="userInfo" column="user_info"/>
		<result property="headImg" column="head_img" jdbcType="BLOB"/>
		<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
	</resultMap>

	<!-- select查询 -->
	<select id="selectById" resultMap="userMap">
		select * from sys_user where id = #{id}
	</select>

</mapper>

        需要注意的是<mapper>根标签的namespace 属性。当Mapper 接口和XML 文件关联的
时候,命名空间namespace 的值就需要配置成接口的全限定名称

xml映射文件中标签含义:

  • <select>: 映射查询语句使用的标签。
  •  id:命名空间中的唯一标识符,可用来代表这条语句。
  • select 标签中的select * from sys_user where id= #{id}是查询语句。
  • # {id} : MyBatis SQL 中使用预编译参数的一种方式,大括号中的id 是传入的参数名。
  • resultMap:用于设置返回值的类型和映射关系。 

        resultMap 标签用于配置Java 对象的属性和查询结果列的对应关系,通过 resultMap中配置的column 和property 可以将查询列的值映射到type 对象的属性上。

2.4 创建XML文件对应的接口类

public interface UserMapper {
    /**
     * 通过ID查询用户
     * @param id
     * @return
     */
    SysUser selectById(Long id);

}

        接口中定义的返回值类型必须和泊位中配置的resultType 类型一致,否则就会因为类型不一致而抛出异常。 xml方式下,返回值类型是由XML 中的resultType (或 resultMap 中的type)决定的,不是由接口中写的返回值类型决定的

2.5 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>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

    <typeAliases>
        <package name="com.wyf.mybaties.model"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.wyf.mybaties.mapper" />
    </mappers>

</configuration>

在配置文件中,我们可以直接在<mappers>指定映射文件,如下

<mappers> 
        <mapper resource=”com/wyf/mybaties/mapper/CountryMapper.xml ” / >
        <mapper resource=”com/wyf/mybaties/mapper/UserMapper.xml ” / >
        <mapper resource=”com/wyf/mybaties/mapper/RoleMapper.xml” />
        <mapper resource=”com/wyf/mybaties/mapper/PrivilegeMapper.xml ” />
        <mapper resource=”com/wyf/mybaties/mapper/UserRoleMapper.xml ” />
        <mapper resource=”com/wyf/mybaties/mapper/RolePrivilegeMapper.xml ” />
</mappers>

        这种配置方式需要将所有映射文件一一列举出来,如果增加了新的映射文件,还需要注意在此处进行配置,操作起来比较麻烦。由于此处所有的XML映射文件都有对应的Mapper 接口所以还有一种更简单的配置方式,代码如下:

    <mappers>
        <package name="com.wyf.mybaties.mapper" />
    </mappers>

        这种配置方式会先查找包com.wyf.mybaties.mapper下所有接口,循环对接口进行如下操作:

  1. 判断接口对应的命名空间是否己经存在,如果存在就抛出异常,不存在就继续进行接下来的操作;
  2. 加载接口对应的XML映射文件, 将接口全限定名转换为路径。 例如, 将接口com.wyf.mybaties.mapper.UserMapper 转换为com/wyf/mybaties/mapper/UserMapper. xml,
    然后以.xml 为后缀搜索XML 资源,如果找到就解析XML。
  3. 处理接口中的注解方法。

三、方法测试:

3.1 select用法

        我们需要查询数据库中的数据。 在使用纯粹的 JDBC 时,需要写查询语句,并且对结果集进行手动处理, 将结果映射到对象的属性中。使用MyBatis 时,只需要在XML 中添加一个select 元素,写一个SQL, 再做一些简单的配置,就可以将查询的结果直接映射到对象中。

        如上节示例,我们在xml映射文件以及对应的接口文件添加了一个根据用户 id 查询用户信息的简单方法。

        前面创建接口和XML时提到过,接口和XML是通过将namespace 的值设置为接口的全限定名称来进行关联的,那么接口中方法和XML又是怎么关联的呢?

        通过前文代码,我们可以发现XML 中的 select 标签的id 属性值和定义的接口方法名是一样的MyBatis ,就是通过这种方式将接口方法和XML中定义的SQL语句关联到一起的,如果接口方法没有和XML 中的id 属性值相对应,启动程序便会报错。映射XML和接口的命名需要符合如下规则:

  • 当只使用XML而不使用接口的时候, namespace 的值可以设置为任意不重复的名称。
  • 标签的id 属性值在任何时候都不能出现英文句号“.”,并且同一个命名空间下不能出现重复的id。
  • 因为接口方法是可以重载的,所以接口中可以出现多个同名但参数不同的方法,但是XML 中 id 的值不能重复,因而接口中的所有同名方法会对应着XML 中的同一个id的方法。最常见的用法就是,同名方法中其中一个方法增加一个 RowBound 类型的参数用于实现分页查询。

测试代码如下:

/**
 * 基础测试类
 */
public class BaseMapperTest {
    private static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static  void init(){
        try{
            Reader reader= Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            reader.close();
        }catch(IOException ex){
            ex.printStackTrace();
        }
    }

    /**
     * 由SqlSessionFactory工厂对象,生产SqlSession
     * @return
     */
    public SqlSession getSqlSession (){
        return sqlSessionFactory.openSession();
    }
}

测试: 

public class UserMapperTest extends BaseMapperTest{
    @Test
    public void TestSelectById(){
        //获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try{
            //获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //调用selectByid 方法,查询id = 1 的用户
            SysUser user = userMapper.selectById(1l);
            System.out.println(user.getCreateTime());
        }finally {
            sqlSession.close();
        }
    }
}

3.2 Insert方法

        我们可以在UserMapper.xml中添加如下代码:

	<!-- insert数据插入 -->
	<insert id="insert">
		insert into sys_user(
			user_name, user_password, user_email, 
			user_info, head_img, create_time)
		values(
			#{userName}, #{userPassword}, #{userEmail}, 
			#{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
	</insert>

         此处<insert>中的 SQL 就是一个简单的 INSERT 语句,将所有的列都列举出来, 在values 中通过#{property}方式从参数中取出属性的值。

        为了防止类型错误,对于一些特殊的数据类型,建议指定具体的jdbcType值。 例如headimg 指定BLOB 类型, createTime 指定TIMESTAMP 类型。

我们在与UserMapper.xml相关联的接口中,添加对应的方法:

    /**
     * 新增用户
     *
     * @param sysUser
     * @return 返回影响行数
     */
    int insert(SysUser sysUser);

编写测试代码:

    /**
     * insert方法测试
     */
    @Test
    public void InsertToUser(){
        //获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try{
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser sysUser = new SysUser();
            sysUser.setUserName("wyf");
            sysUser.setUserPassword("111111");
            sysUser.setUserEmail("wyf@book.com");
            sysUser.setUserInfo("wyf info");
            sysUser.setHeadImg(new byte[]{1,2,3}); //实际是一张图片
            sysUser.setCreateTime(new Date());

            //将新建的对象插入数据库中,返回值result 是执行的SQL 影响的行数
            int res = userMapper.insert(sysUser);
            System.out.println("数据插入执行结果:"+res);
        }finally {
            //默认的sqlSessionFactory.openSession()是不自动提交的
            //因此不手动执行commit 也不会提交到数据库
            sqlSession.commit(); //提交数据插入
            sqlSession.close();
        }
    }

3.3 upDate方法

        在UserMapper.xml映射文件中添加以下方法:

	<!-- update 数据更新 -->
	<update id="updateById">
		update sys_user
		set user_name= #{userName} ,
			user_password= #{userPassword},
			user_email = #{userEmail} ,
			user_info= #{userInfo} ,
			head_img = #{headImg , jdbcType=BLOB} ,
			create_time = #{createTime , jdbcType=TIMESTAMP}
		where id = #{id}
	</update>

        在UserMapper.xml映射文件对应的接口文件中添加相应的方法:

	/**
	 * 根据主键更新
	 * 
	 * @param sysUser
	 * @return
	 */
	int updateById(SysUser sysUser);

 编写测试代码:

    /**
     * Update方法测试
     */
    @Test
    public void UpDateToUser(){
        //获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try{
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //从数据库查询获取一个user对象
            SysUser sysUser = userMapper.selectById(1L);
            //修改
            sysUser.setUserName("wyf_test");
            sysUser.setUserPassword("123456");
            sysUser.setUserEmail("wyf_test@book.com");

            //更新数据,返回影响行数
            int res = userMapper.updateById(sysUser);
            System.out.println("数据修改执行影响结果:"+res);
        }finally {
            //默认的sqlSessionFactory.openSession()是不自动提交的
            //因此不手动执行commit 也不会提交到数据库
            sqlSession.commit(); //提交数据插入
            sqlSession.close();
        }
    }

3.4 delete方法

        在UserMapper.xml文件中添加以下方法:

	<!-- delete删除数据 -->
	<delete id="deleteById">
		delete from sys_user where id = #{id}
	</delete>

        在UserMapper.xml映射文件对应的接口文件中添加相应的方法:

    /**
     * 通过主键删除
     *
     * @param id
     * @return
     */
    int deleteById(Long id);

测试代码:

    /**
     * delete方法测试
     */
    @Test
    public void DeleteToUser(){
        //获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try{
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //从数据库查询获取一个user对象
            SysUser sysUser = userMapper.selectById(1L);
            //删除对象
            int res = userMapper.deleteById(sysUser.getId());
            System.out.println("数据修改执行影响结果:"+res);
        }finally {
            //默认的sqlSessionFactory.openSession()是不自动提交的
            //因此不手动执行commit 也不会提交到数据库
            sqlSession.commit(); //提交数据
            sqlSession.close();
        }
    }

 3.5 多个接口参数的用法

        通过观察,不难发现目前所列举的接口中方法的参数只有一个,参数的类型可以分为两种:一种是基本类型,另一种是JavaBean。

        当参数是一个基本类型的时候,它在XML文件中对应的SQL 语句只会使用一个参数,例如delete 方法。当参数是一个JavaBean 类型的时候,它在XML文件中对应的SQL语句会有多个参数,例如insert、 update 方法。

        在实际应用中经常会遇到使用多个参数的情况。之前例子中,我们将多个参数合并到一个JavaBean 中,并使用这个JavaBean 作为接口方法的参数。这种方法用起来很方便,但并不适合全部的情况,因为不能只为了两三个参数去创建新的JavaBean 类,因此对于参数比较少的情况,还有两种方式可以采用:使用Map 类型作为参数或使用@Param 注解。

	<!-- 多参数 -->
	<select id="selectRolesByUserIdAndRoleEnabled" resultType="com.wyf.mybaties.model.SysRole">
		select
			r.id,
			r.role_name roleName,
			r.enabled,
			r.create_by createBy,
			r.create_time createTime
		from sys_user u
				 inner join sys_user_role ur on u.id = ur.user_id
				 inner join sys_role r on ur.role_id = r.id
		where u.id = #{userId} and r.enabled = #{enabled}
	</select>

接口方法中,参数要添加注解:

    /**
     * 根据用户 id 和 角色的 enabled 状态获取用户的角色
     *
     * @param userId
     * @param enabled
     * @return
     */
    List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("userId")Long userId, @Param("enabled")Integer enabled);

        给参数配置@Param注解后, MyBatis 就会自动将参数封装成Map 类型,@Param 注解值
会作为Map 中的key,因此在SQL 部分就可以通过配置的注解值来使用参数。

四、结束

        本文介绍了MyBatis使用XML的配置方式,并基于其实现了select、insert、update和delete操作。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值