MyBatis原理及使用——MyBatis(一)
MyBatis原理及使用
一、框架
概念:框架是一套完整的解决方案的可重用的代码,包含了一组抽象构件和构件间交互的方法。
二、Mybatis框架
是一个基于Java的持久层框架,封装了JDBC,使开发者只需要关注SQL语句本身而无需操心加载驱动,创建连接,创建Statement等繁琐的过程。
可以通过xml或注解的方式配置Statement,并通过java对象和Statement中SQL的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行SQL语句并将结果通过ORM映射为Java对象并返回。
ORM实现了实体和数据库映射的问题,对JDBC进行了封装,屏蔽了JDBC Api底层访问的细节,使用户更专注于数据库的操作。
使用步骤:
以操作数据库的user表为例(user包含id,username, birthday, sex, address属性)。
1. 创建user表的Java Bean类--User类
2. 创建user表的Dao层接口。在接口中包括了user表的增删改查等方法。
3. 配置Mybatis的SqlMapConfig.xml文件,在文件中配置数据库连接信息和数据库访问层信息。
4. 配置数据库访问层具体接口的UserDao.xml文件,配置方法的方法名、参数类型、返回值类型以及SQL语句等
4.或通过注释方法配置接口。
5. 通过mybatis执行创建接口UserDao的代理类 ,通过代理类执行SQL语句,返回执行结果。
三、使用流程
1. xml配置方法
- 创建User表的Bean类
- 创建操作数据库的接口UserDao
- 配置Mybatis的文件:SqlMapConfig.xml
<?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="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/hellossm?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/one/mybatis/dao/UserDao.xml"/> </mappers> </configuration>
- 配置接口映射文件:UserDao.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"> <!--namespace是数据访问层类--> <mapper namespace="com.one.mybatis.dao.UserDao"> <!-- id是方法名--> <select id="findAll" resultType="com.one.mybatis.domain.User"> select * from user </select> </mapper>
注意,UserDao.xml在resource下的结构必须与UserDao相同
2. Web配置方法
- 创建User表的Bean类
- 创建操作数据库的接口UserDao
- 配置Mybatis的文件:SqlMapConfig.xml
<?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="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/hellossm?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.one.mybatis.dao.UserDao"/> </mappers> </configuration>
- 配置Dao接口(移除Dao的xml配置文件,否则可能报错)
public interface UserDao { @Select("select * from user") List<User> findAll(); }
注意:UserDao接口可以创建实现类,但是为了程序更简洁,不推荐实现
3. Mybatis使用模板
1.读取Mybatis配置文件
-方法1:使用类加载器Resources,读取类路径的配置文件(resource下的文件)
-方法2:使用ServletContext对象,获得文件的真实路径getRealPath()
2.创建SqlSessionFactoryBuilder
3.创建SqlSessionFactory工厂:build(in)
构建者模式:把创建Factory的细节隐藏,使使用者直接调用方法即可拿到工厂对象。
4.创建SqlSession对象: factory.openSession()
工厂模式:通过工厂类创建Session对象,解耦(降低类之间的依赖关系)
5.创建Dao接口的代理对象: session.getMapper()
代理模式:代替执行;不修改源码的基础上对已有的方法进行增强。
6.使用代理对象执行方法:List<User> users = proxy.findAll();
public class SelectDemo {
public static void main(String[] args) throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
UserDao proxy = session.getMapper(UserDao.class);
List<User> users = proxy.findAll();
for (User user : users)
System.out.println(user);
session.close();
in.close();
}
}
四 Mybatis参数
1. parameterType:参数类型
- Java类型:int/double、Integer、String等
- Java Bean对象:使用OGNL表达式解析对象的值,#{username}
- Java Bean的包装类对象:如UserBox, 解析为#{user.username}
OGNL(Object Graphic navigation Language, 对象图导航语言)表达式:
*通过对象直接取值; 拿取的是get方法的值,第一个字母小写。 如:user.getUserName()àuser.username
*mybatis配置中,可以省略对象直接取值。(因为parameterType已经提供了对象所属的类,所以此时不需要写对象), 如:#{user.username}à#{username}
2. returnType: 返回类型
- Java类型:int,Integer,String
- Java Bean对象
- Java Bean列表
当返回类型与Bean类的属性名对不上时,就无法封装数据,解决方法:在xml中resultMap标签中重新配置返回类型,在resultMap中配置数据库属性与类属性之间的对应关系。
<resultMap id="userMapper" type="com.one.mybatis.domain.User">
<!-主键的对应-->
<id property="id" column="id"></id>
<!--非主键的对应-->
<result property="Birthday" column="birthday"></result>
<result property="UserName" column="username"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</resultMap>
<select id="findAll" resultMap="userMapper">
select * from user
</select>
3. Properties标签:存储数据库的配置信息
配置方法1:在Properties标签中配置数据库的信息,在dataSource中以${}形式使用。
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="1234"/>
</properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
配置方法2:
在标签中引入数据库配置信息的properties文件,在dataSource中以${}形式使用。
resource:数据库的类路径,文件必须存储在类路径下。
<properties resource="jdbc.properties"></properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
配置方法3:
以URI的方式引入数据库配置文件
- URL:统一资源定位符,唯一标识一个资源的路径,写法:协议/主机/端口/位置
- URI:统一资源标识符,在应用中唯一定位一个资源
<properties url="http://www.baidu.com/jdbc.properties"></properties>
<properties url="D:/file/jdbc.properties"></properties>
4. typeAliases标签:类名别名
在 SqlMapConfig.xml 中配置:
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.itheima.domain.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.itheima.domain"/>
</typeAliases>
5. package标签:类名别名;代替mapper映射
1. 类名别名:包下所有包名.类名都可以只用类名代替(首字母大小写都可以)。
别名不仅可以在mybatis配置文件里使用,在dao的配置文件里也能使用
2. 映射信息:代替mapper,注册包下所有接口与配置文件的关系。
此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
<mappers>
<!--<mapper resource="com/one/mybatis/dao/UserDao.xml"/>-->
<package name="com.one.mybatis.dao"/>
</mappers>
6. plugins分页标签
将分页查询的复杂操作进行封装,使用户简单地实现分页查询操作。
步骤:
- 导入分页所需的包:
com.github.pageHelper.pagehelper-3.7.5
com.github.jsqlparser.jsqlparser.0.9.1
2. 配置mybatis的xml文件,支持分页查询
<!--在configuration标签下配置-->
<!--配置分页-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!--sql语言的查询-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
3. 使用PageHelper实现分页查询
@Test
public void findAll()
{
PageHelper helper=new PageHelper();
helper.startPage(1, 3);
List<User> users=dao.findAll();
for (User user : users) {
System.out.println(user);
}
}
五、CRUD方法
Dao层xml文件中,实现数据库的CRUD操作方式
1. 查询所有用户信息
<select id="findAll" resultType="com.one.mybatis.domain.User">
select * from user
</select>
2.查询用户信息通过id
<select id="findById" parameterType="int" resultType="com.one.mybatis.domain.User">
select * from user where id=#{userId};
</select>
3.查询用户信息,通过模糊姓名
<select id="findByName" parameterType="String" resultType="com.one.mybatis.domain.User">
select * from user where username like #{username};
</select>
4.查询用户总数
<select id="findCount" resultType="int">
select count(*) from user;
</select>
5.插入用户信息User,并将id保存到User中
<insert id="insertUser" parameterType="com.one.mybatis.domain.User">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username, birthday, sex, address) values(#{username},#{birthday},#{sex},#{address});
</insert>
6.更新用户信息,通过id
<update id="updateUser" parameterType="com.one.mybatis.domain.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id};
</update>
7.删除用户信息,通过id
<delete id="deleteById" parameterType="java.lang.Integer">
delete from user where id=#{userId};
</delete>
六、Mybatis源码
- SqlSession调用getMapper(UserDao.class)
- SQLSession实现类中的getMapper调用Configuration的getMapper方法
- Configuration解析xml配置文件,将mapper映射为MapperRegister,并将mapper中的Dao类名和Dao的xml文件信息以键值对的形式传给MapperRegister,调用MapperRegister的getMapper方法
- MapperRegister根据type类型,获得type的代理类工厂MapperProxyFactory(代理工厂中包含了type的各种信息,如Interface,methodCache)。
- MapperProxyFactory创建代理类处理器MapperProxy,传入SqlSession,并创建type的代理类
- 代理类处理器的invoke方法中使用SqlSession执行SQL语句。