Mybatis实现入门级的简单增删改查
与Hibernate类似,MyBatis也是一个持久层的框架,关于该框架的类型,介绍有很多,这里就不再赘述。因为是初次接触,所以遵循一个循序渐进的过程,先使用该框架实现最基本的配置操作。对其中使用到的对象以及配置过程先做出简单的说明。后续随着学习的深入对特定知识再做出详细的总结。
本文仅使用一个简单的实体类User作为操作对象。仅包含两个属性:id以及name,并在数据库建立了与之对应的表。
1.准备
- 下载Mybatis框架,且框架的zip包里面已经包含了所需要的依赖包。新建工程进行导入。简单的常规流程。
- 建立实体类,以及数据库和对应表。
2.配置Mybatis属性文件
与Hibernate一样,对于Mybatis,也是需要进行配置文件的设置的。但是在Mybatis里面。对属性的文件名以及其存放位置并没有做硬性的要求。而Mybatis的属性配置,它决定了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>
<environments default="development">
<environment id="development">
<!--使用JDBC事务管理,由Mybatis控制-->
<transactionManager type="JDBC"/>
<!--指定使用的数据源,由Mybatis管理,有以下的几个可选值 -->
<!-- POOLED 表示支持JDBC数据源连接池 -->
<!-- UNPOOLED 表示不支持数据源连接池 -->
<!-- JNDI 表示支持外部数据源连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_test"/>
<property name="username" value="root"/>
<property name="password" value="131421"/>
</dataSource>
</environment>
</environments>
<!--加载配置文件, resource属性是以src为开始路径, 此处对User的映射文件为UserMapper.xml-->
<mappers>
<!--添加一个具体的映射文件-->
<mapper resource="config/sqlMap/UserMapper.xml"/>
<!-- 指定目录,将自动添加该目录下的所有映射文件 -->
<package name="config/sqlMap"/>
</mappers>
</configuration>
3.配置实体类(User)的映射文件
在Mybatis里面,映射文件不是像Hibernate那样仅仅只是建立二者的关系而已。它可以用来建立一个针对一个特定接口的实现规则,描述其实现方法的具体形式。这里先侧重于了解如何编写方法的实现规则。对其映射关系先不做深入。
<?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代理的形式,所以先名为Test -->
<mapper namespace="Test">
<!--
建立一个指定功能(insert、update,delete,select)的标签,并设定其属性,后续在映射接口方法的时候,根据该标签调用SqlSession的不同方法
然后该select标签体的SQL语句会被渲染为一个MappedStatement对象。
该MappedStatement对象的引用标识就是select标签的id
后续在SqlSession对象在进行查找等操作的时候,需要指定使用哪个MappedStatement对象来进行操作,指定方法:【命名空间.id名称】
id :
该SQL语句将会封装到MappedStatement对象里面。id用于标识封装本SQL语句的对象
#{ }
表示一个占位符,传递进来的变量会首先尝试进行计算,然后在填充到语句里面,比如:#{ 3-1}
其内部的变量名可以任意,
可以接收简单数据类型,实体类以及集合类
传递实体类的话可以直接写为:#{ 属性 } 来获取这个实体类的某个属性
${ }
仍表示一个拼接符,内部的变量名必须是value。在调用的时候,调用的值会原封不动的传递进来而不进行运算。
如果传递的值要原封不动的应用在一个字符串内部,
如果传递的是简单的数据类型,那么必须使用${ value }
parameterType:
指定输入参数的类型, 可以是简单类型,也可以是实体类或集合
resultType:
指定【单条记录】的存储类型,即便查询语句得到的结果是多条信息,还是要使用单条信息的数据类型
如果所查的信息是对象,则指定其全路径。
以下的两个查询语句都可能会返回多条信息,但是每条信息都是一个User对象,所以resultType = User。
-->
<!--
示例:
针对User接口实现一个“方法”,名称为selectUserByName, 传递给其一个String类型的参数,它将返回一个User对象或一个包含User对象对的集合
-->
<select id="selectUserByName" resultType="domain.User" parameterType = "java.lang.String">
select * from tb_user where name like '%${value}%'
</select>
<select id="selectUserById" resultType="domain.User" parameterType="int">
select * from tb_user where id = ${value}
</select>
<!--
当传递的对象不再是简单的数据类型的时候,比如插入,传递的就是一个User实体类对象。
那么可以使用下面的方法进行设置,其中占位符里面分别对应的是User里面的各个属性,
后续在传入一个User对象的时候,占位符的会自动解析出该对象所包含的各个属性并添加到指定位置
在进行插入操作的时候,可以获取插入之后该条记录的主键值,可以使用select LAST_INSERT_ID();
但仅适用于主键自增的情况下。
使用selectKey标签,来操作所传入实体类的。使用keyProperty选择要操作的具体属性
order表示在何时执行。AFTER指的是在执行完insert标签体的insert语句之后再执行,BEFORE则是之前。
resultType指的是操作完返回结果的类型。
同样以下面的插入标签为例。在执行完insert插入的操作之后,再执行selectKey标签的内容,
获取所传递的实体类,执行SELECT LAST_INSERT_ID()获取上次插入时所使用的主键值,并作为结果
返回给所操作实体类的id属性,这样的话,在外部就可以使用getID()来获取本条语句插入时候所使用的主键。
而对应非自增的主键,当要设置其主键的时候,可以选择在程序自己指定,也可以使用函数 UUID() 来生成一个主键。
采用此方法的时候,主键的类型就需要调整为String类型。并且使用selectKey标签,设置order为BEFORE, 因为
要在进行插入之前获取一个ID, 然后设置给传递进来的实体,最后再持久化到数据库。
在其标签体内部使用 select UUID() 从数据库获取一个主键,并返回给所传递进来的User实体的id属性。
然后再执行insert语句,此时所设置的id就是UUID() 获取到的主键了
-->
<insert id="insertUser" parameterType = "domain.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
insert into tb_User values (#{id}, #{name});
</insert>
<!--同样的步骤设置删除与更新的操作-->
<delete id="deleteUser" parameterType = "java.lang.Integer">
delete from tb_User where id =#{id};
</delete>
<update id="updateUser" parameterType = "domain.User">
update tb_user set name = #{name} where id = #{id};
</update>
</mapper>
4.使用映射文件所定义的‘方法’进行操作
Mybatis进行操作时候,各个类之间的简单关系流程如下图所示,操作的时候,所进行的过程也与之相对应:
这里先不使用mapper代理对象的形式调用。
@Test
public void test(){
InputStream is = null;
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
try {
//获取配置文件
is = Resources.getResourceAsStream("config/SqlMapConfig.xml");
//构建工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//获取SqlSession
sqlSession = sqlSessionFactory.openSession();
/*
* 查询一条结果,第一个变量用于确定所要执行哪个命名空间的哪个标签语句,
* 此处的Test.selectUserById就是为User接口实现的方法之一,这里是直接调用
* 第二个就是所指定的参数值,类型要与在标签建立语句时候指定的一致。
* selectOne()查询一条结果,返回的结果就是建立标签是所指定的结果类型
* */
User user1 = sqlSession.selectOne("User.selectUserById", 1);
System.out.println(user1.toString());
/*
* 查询多条结果
* 参数同上,selectList()用于查询一个集合,结果集里面的每个对象与建立标签时候所指定的输出对象类型一致
* */
List<User> list = sqlSession.selectList("Test.selectUserByName", "大");
System.out.println(list);
/*
* 删除信息
* */
sqlSession.delete("Test.deleteUser", 14);
sqlSession.commit();
/*
* 插入信息
* */
User user3 = new User();
user3.setName("嘻嘻嘻");
sqlSession.insert("Test.insertUser", user3);
sqlSession.commit();
System.out.println(user3.getId());
/*
* 修改信息
* */
User user4 = new User();
user4.setId(5);
user4.setName("嘿嘿");
sqlSession.update("Test.updateUser", user4);
sqlSession.commit();
}catch(IOException e) {
throw new IOException();
}finally {
sqlSession.close();
}
}
简单总结下,在进行调用的时候,首先就是确定所要使用哪个命名空间下哪个操作,然后传入与设定标签所对应的操作,并进行接收。在进行除查询之外的操作后,需要进行提交。当然后续会直接使用mapper代理对象来调用所设置的方法。不需要这种形式的调用。此处只是为了描述映射文件的写法
Mybatis进行基本的映射文件编写大致如此。第一次接触,对一些概念性的问题还是更多的还是处于一知半解的状态,随着后续学习的深入,再对之前文章中存在疑问或理解错误的地方进行更改。