Mybatis(初级)学习笔记
Mybatis是一个持久层的框架,是一个不完全的ORM框架。特点是让程序员将主要精力放到sql上,通过Mybatis提供的映射方式,自由灵活的生成满足需要的sql语句。
原理图
SqlMapCogfig.xml(是Mybatis的全局配置文件)配置了数据源,事务等运行环境
配置映射文件(配置sql语句)mapper.xml、mapper.xml...
↓
SqlSessionFactory (会话工厂) 根据配置文件创建会话工厂 作用:得到会话
↓
SqlSession(会话) 它是一个面向程序员的接口
作用:操作数据库(发出CRUD的sql操作)
↓
Executor(执行器) 它也是一个接口( 基本执行器、缓存执行器)
作用:SqlSession内部通过执行器操作数据库
↓
mapped statement(底层封装对象)
↓
mysql
入门程序
需求:使用Mybatis操作数据库
流程:
1.配置Mybatis的配置文件,SqlMapConfig.xml(名称不是固定的),SqlMapConfig.xml需要配置环境(数据源), mapper的加载和事务。
2. 通过配置文件,加载mybatis的运行环境,创建会话工厂SqlSessionFactory,SqlSessionFactory实际使用时按照单例进行管理
3.通过SqlSessionFactory创建SqlSession,SqlSession是一个面向用户的接口(提供操作数据库的方法),实现对象是线程不安全的,建议SqlSession应用场合放到方法体内部。
4.调用sqlSession的方法去操作数据
如果需要提交事务,需要执行SqlSession的commit()方法。
5.释放资源,关闭SqlSession。
数据库内容如下
1.配置Mybatis的全局配置文件SqlMapConfig.xml
(1)配置相关环境,数据源事务等
(2)配置加载sql语句的配置文件
<?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"> <!--配置环境,与Spring整合后由Spring进行管理--> <environment id="development"> <!--启用jdbc事务管理,事务控制由Mybatis管理(后面交由Spring管理)--> <transactionManager type="JDBC"/> <!--配置数据库连接池参数,由Mybatis管理(后面交由Spring管理)--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/how2j?characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--加载sql语句的配置文件--> <mappers> <!--使用class按包加载--> <mapper resource="Config/sqlmap/User.xml"/> </mappers> </configuration>
2.配置sql语句的配置文件User.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"> <!--在此配置文件中配置Sql语句--> <!--namespace为命名空间,其中填写的是Mapper接口的路径,但是这里不用Mapper接口,所以随意填写--> <mapper namespace="test"> <!-- #{}表示一个占位符, #{id}表示接收的参数,如果输入参数为简单类型则可以随意填写 resultType是用来指定输出结果所映射的Java对象--> <select id="findCategoryById" parameterType="int" resultType="Pojo.Category"> SELECT * FROM category_ WHERE id = #{id} </select> </mapper>
3.编写输出映射的Pojo对象类(这个是根据数据库查找的数据所写)
package Pojo; public class Category { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Category{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
4.进行Test
public class MybatisTest { @Test public void findUserById() throws IOException{ /*定义Mybatis的配置文件*/ String resource = "SqlMapConfig.xml"; /*得到配置文件流*/ InputStream inputStream = Resources.getResourceAsStream(resource); /*创建会话工厂,传入Mybatis配置参数*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /*通过会话工厂得到会话*/ SqlSession sqlSession = sqlSessionFactory.openSession(); /*通过SqlSession操作数据库 第一个参数,映射文件中statement的id,等于=namespace+“.”+id 第二个参数,指定和映射文件中所匹配的parameterType类型参数*/ Category category = sqlSession.selectOne("test.findCategoryById",1); System.out.println(category); /*关闭会话,释放资源*/ sqlSession.close(); } }
5.得到结果
模糊查询
1.在User.xml中加入模糊查询的Sql语句
<!--${}表示拼接sql串,将接收到参数的内容不加修饰拼接在sql语句中,但是可能导致sql注入 ${value}:接收到如数参数内容,如果传入的是简单类型,${}中只能写value --> <select id="findCategoryByName" parameterType="String" resultType="Pojo.Category"> SELECT * FROM category_ WHERE name like '%${value}%' </select>
2.写Test程序
public class MybatisTest { @Test public void findUserById() throws IOException{ /*定义Mybatis的配置文件*/ String resource = "SqlMapConfig.xml"; /*得到配置文件流*/ InputStream inputStream = Resources.getResourceAsStream(resource); /*创建会话工厂,传入Mybatis配置参数*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /*通过会话工厂得到会话*/ SqlSession sqlSession = sqlSessionFactory.openSession(); /*通过SqlSession操作数据库 第一个参数,映射文件中statement的id,等于=namespace+“.”+id 第二个参数,指定和映射文件中所匹配的parameterType类型参数*/ List<Category> list = sqlSession.selectList("test.findCategoryByName","ca"); System.out.println(list); /*关闭会话,释放资源*/ sqlSession.close(); } }
3.得到结果
插入用户
1.在User.xml中加入插入的Sql语句
<!--#{}中填写的是传入pojo中的属性名--> <insert id="insertCategory" parameterType="Pojo.Category"> INSERT INTO category_(id,name) value(${id},"${name}") </insert>
2.写Test程序
public class MybatisTest { @Test public void findUserById() throws IOException{ /*定义Mybatis的配置文件*/ String resource = "SqlMapConfig.xml"; /*得到配置文件流*/ InputStream inputStream = Resources.getResourceAsStream(resource); /*创建会话工厂,传入Mybatis配置参数*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /*通过会话工厂得到会话*/ SqlSession sqlSession = sqlSessionFactory.openSession(); /*设置插入Pojo*/ Category category = new Category(); category.setName("cxx"); /*通过SqlSession操作数据库 第一个参数,映射文件中statement的id,等于=namespace+“.”+id 第二个参数,指定和映射文件中所匹配的parameterType类型参数*/ sqlSession.insert("test.insertCategory",category); sqlSession.commit(); /*关闭会话,释放资源*/ sqlSession.close(); }
3.得到结果
删除用户
1.在User.xml中加入插入的Sql语句
<!--根据id值删除信息,需要输入id值--> <delete id="deleteCategory" parameterType="int"> DELETE FROM Category_ WHERE id=#{id} </delete>
2.写Test程序
public class MybatisTest { @Test public void findUserById() throws IOException{ /*定义Mybatis的配置文件*/ String resource = "SqlMapConfig.xml"; /*得到配置文件流*/ InputStream inputStream = Resources.getResourceAsStream(resource); /*创建会话工厂,传入Mybatis配置参数*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /*通过会话工厂得到会话*/ SqlSession sqlSession = sqlSessionFactory.openSession(); /*通过SqlSession操作数据库 第一个参数,映射文件中statement的id,等于=namespace+“.”+id 第二个参数,指定和映射文件中所匹配的parameterType类型参数*/ sqlSession.delete("test.deleteCategory",5); sqlSession.commit(); /*关闭会话,释放资源*/ sqlSession.close(); } }
3.得到结果
更新用户
1.在User.xml中加入插入的Sql语句
<!--设置好传入的pojo,里面包括id和更新的信息--> <update id="updateCategory" parameterType="Pojo.Category"> UPDATE Category_ set name=#{name} where id=#{id} </update>
2.Test
public class MybatisTest { @Test public void findUserById() throws IOException{ /*定义Mybatis的配置文件*/ String resource = "SqlMapConfig.xml"; /*得到配置文件流*/ InputStream inputStream = Resources.getResourceAsStream(resource); /*创建会话工厂,传入Mybatis配置参数*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /*通过会话工厂得到会话*/ SqlSession sqlSession = sqlSessionFactory.openSession(); Category category = new Category(); category.setId(3); category.setName("lalaala"); /*通过SqlSession操作数据库 第一个参数,映射文件中statement的id,等于=namespace+“.”+id 第二个参数,指定和映射文件中所匹配的parameterType类型参数*/ sqlSession.update("test.updateCategory",category); sqlSession.commit(); /*关闭会话,释放资源*/ sqlSession.close(); } }
3.得到结果
别名定义
在sqlMapconfig.xml中可以定义别名,让Statement中的参数可以直接写类名,而不是全路径。
<!--定义别名,在写Statement的时候就可以直接输入类名--> <typeAliases> <package name="Pojo"></package> </typeAliases>
Mapper代理开发
1.编写Mapper接口
public interface CategoryMapper { public Category findCategoryById(int id) throws Exception; public List<Category> findCategoryByName(String name) throws Exception; public void insertCategory (Category category)throws Exception; }
2.配置Sql语句
<!--Mapper代理开发,namespace等于Mapper接口的地址--> <mapper namespace="Mapper.CategoryMapper"> <!-- #{}表示一个占位符, #{id}表示接收的参数,如果输入参数为简单类型则可以随意填写 resultType是用来指定输出结果所映射的Java对象--> <select id="findCategoryById" parameterType="int" resultType="Pojo.Category"> SELECT * FROM category_ WHERE id = #{id} </select> <!--${}表示拼接sql串,将接收到参数的内容不加修饰拼接在sql语句中,但是可能导致sql注入 ${value}:接收到如数参数内容,如果传入的是简单类型,${}中只能写value --> <select id="findCategoryByName" parameterType="String" resultType="Pojo.Category"> SELECT * FROM category_ WHERE name like '%${value}%' </select> <!--#{}中填写的是传入pojo中的属性名--> <insert id="insertCategory" parameterType="Pojo.Category"> INSERT INTO category_(id,name) value(${id},"${name}") </insert> <!--根据id值删除信息,需要输入id值--> <delete id="deleteCategory" parameterType="int"> DELETE FROM Category_ WHERE id=#{id} </delete> <!--设置好传入的pojo,里面包括id和更新的信息--> <update id="updateCategory" parameterType="Pojo.Category"> UPDATE Category_ set name=#{name} where id=#{id} </update> </mapper>
3.写Test实现
public class MapperTest { /*通过单例方式管理SqlSessionFactory*/ /*通过单例方式管理SqlSessionFactory*/ private SqlSessionFactory sqlSessionFactory; @Before public void serUp() throws Exception{ /*重复的代码抽取*/ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void findCategoryByID()throws Exception{ SqlSession sqlSession = sqlSessionFactory.openSession(); /*加载Mapper文件*/ CategoryMapper categoryMapper = sqlSession.getMapper(CategoryMapper.class); Category category = categoryMapper.findCategoryById(1); System.out.println(category); sqlSession.close(); } }
4.结果
总结:
编写Mapper接口的时候需要遵循的一些开发规范:
1.接口中的方法名称需要和statement中的id一致
2.接口中的方法参数需要和statement中的parametertype一致
3.接口中的方法返回值需要和statement中的resultType一致
4.mapper的namespace中需要传入Mapper接口的全路径
Mybatis的核心:动态sql
通过if表达式判断,对sql进行灵活的拼接,组装。
需求:使用动态sql进行用户信息的综合查询列表statement的定义
<select id="findCategoryById" parameterType="Pojo.Category" resultType="Pojo.Category"> SELECT * FROM category_ <where> <if test="id!=null"> id = #{id} </if> </where> </select>
sql片段的使用
在mapper.xml中定义抽取重复的sql代码,组成一个sql片段,这样在其他的statement中就可以使用sql片段
1.定义sql片段
<!--定义sql片段,但是不要包括where--> <sql id="query"> <if test="id!=null"> id = #{id} </if> </sql>
2.引用使用include标签来引用sql片段,如果引用的sql片段不在本个mapper的namespace里面,则前面需要加上其他namespace的名称
<select id="findCategoryById" parameterType="Pojo.Category" resultType="Pojo.Category"> SELECT * FROM category_ <where> <include refid="query"/> /*y用include标签引用sql片段*/ </where> </select>