文章目录
掌握了这些,你才算真正的Mybatis入门😊
概述
Mybatis是SSM框架中的M,百度百科,是一个优秀的持久层框架,对jdbc过程进行封装,更加专注于SQL。本文将详细的带你快速掌握Mybatis入门操作和配置。
教程
1.jdbc存在的问题及Mybatis和hibernate的区别
jdbc存在的问题
- 频繁对数据库进行连接的创建释放,浪费系统资源
- sql代码不易维护
- 如果查询多个条件,需要where 1==1等前提条件,较为麻烦
- pojo(bean)对象和数据库有关联但是不能利用此关联简化代码
Mybatis如何解决
- 在sqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。
- 将Sql语句配置在XXXXmapper.xml文件中与java代码分离
- Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
- Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
Mybatis和hibernate的区别
Mybatis需要自己写Sql语句,而hibernate可以做到真正的只操作对象实现dao层操作,在更换数据库软件时,Mybatis需要重新编写特定的sql语句,而hibernate只需要改配置即可,由此得出mybatis无法做到数据库无关性。但是,正因为可以自己写sql语句,Mybatis可以利用其灵活的特性编写复杂的服务。
2.环境搭建
2.1下载Mybatis
mybatis-3.2.7.jar mybatis的核心包
lib文件夹 mybatis的依赖包所在
mybatis-3.2.7.pdf mybatis使用手册
2.2.创建配置文件
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
sqlMapConfig.xml
在src下创建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>
<!-- 是用resource属性加载外部配置文件 -->
<properties resource="db.properties"></properties>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="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>
</environment>
</environments>
</environments>
</configuration>
sqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。
log4j.properties
src下创建log4j.properties(日志配置),代码如下
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
mybatis默认使用log4j作为输出日志信息。
2.3创建JavaBean文件
此处需要由你自定义的表结构来写(后续介绍逆向工程可以简化此步骤)
2.4创建sql映射文件
新建包mapper,在其下创建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">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,Mapper动态代理开发的时候使用,需要指定Mapper的类路径 -->
<mapper namespace="com.heima.mapper.UserMapper">
</mapper>
加载映射文件,将users.xml添加在SqlMapConfig.xml,如下:
<mappers>
<!-- <mapper resource="sqlmap/User.xml"/> -->
<!-- 一般项目都用package 此方法要求mapper接口名称和mapper映射文件名称相同并且在同一目录下 -->
<package name="com.heima.mapper"/>
</mappers>
3.写测试代码
3.1编写sql
<!-- 通过id查询一个用户 -->
<select id="findUserById" parameterType="Integer" resultType="User">
select * from user where id = #{v}
</select>
<!-- 根据用户名模糊查询用户列表
#{任意} select * from user where username=? #{}表示占位符=='五' 错误案例:like "%'五'%"找的是中间是'五'
${value} select * from user username like '%五%' 字符串拼接 但是这种会造成sql注入
-->
<select id="findUserByUsername" parameterType="String" resultType="com.heima.domain.User">
select * from user where username like "%"#{v}"%"
</select>
<!-- 添加用户 -->
<insert id="addUser" parameterType="com.heima.domain.User">
<!-- 添加用户返回id -->
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,address,sex)
values (#{username},#{birthday},#{address},#{sex})
</insert>
这里我们注意到入参或者结果是我们定义的类时需要写相对路径,我们可以在sqlMapConfig加入如下代码:
<!-- 别名 包及其子包下所有类 头字母大小写都行 -->
<typeAliases>
<package name="com.heima.domain"/>
</typeAliases>
3.2创建junit包测试
方法通用部分
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession openSession = build.openSession();
编写原始dao开发方式会发现selectOne/selectList很繁琐,我们更推荐用Mapper动态代理方式
3.3Mapper动态代理方式
在Mapper包下新建UserMapper.java接口,并把User.xml重命名UserMapper.xml(原则4用到)
Mapper接口遵循四个原则:
- 接口方法名 ==Mapper.xml中id名
- 返回值类型与Mapper.xml文件中返回值类型要一致
- 方法的入参类型与Mapper.xml中入参类型要一致
- 命名空间绑定此接口
3.4MapperTest
//SqlSession帮我生成一个实现类(给接口)
UserMapper mapper = openSession.getMapper(UserMapper.class);
User user = mapper.findUserById(10);
System.out.println(user);
4.动态sql
如果sql查询字段名和pojo的属性名不一致,需要用到resultMap
if标签,where标签,foreach标签
<sql id="select">//公共部分
select * from user
</sql>
<!-- 根据性别和名字查询用户 where标签可以去掉第一个前and 这样可以不用写1==1-->
<select id="selectUserBySexAndUsername" parameterType="User" resultType="User">
<include refid="select"></include>
<where>
<if test="sex != null and sex != ''">
sex = #{sex}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
</where>
</select>
<!-- 根据多个id查询用户信息 id in(1,2,3)-->
<select id="selectUserByIds" parameterType="QueryVo" resultType="User">
<include refid="select"></include>
<where>
<foreach collection="idList" item="id" separator="," open="id in (" close=")">
#{id}
</foreach>
</where>
</select>
5.关联查询
5.1一对一查询
需要在Orders.java添加User user属性
<!-- 一对一关联查询 以订单为中心关联用户 -->
<resultMap type="Orders" id="order">
<result column="user_id" property="userId"/>
<!-- 只有单表查询才会主动映射,这里所有值都需要手动映射 -->
<result column="id" property="id"/>
<result column="createtime" property="createtime"/>
<result column="number" property="number"/>
<!-- 一对一 -->
<association property="user" javaType="User">
<result column="username" property="username"/>
</association>
</resultMap>
<select id="selectOrdersOneToOne" resultMap="order">
select o.id,o.user_id,o.number,o.createtime,u.username from orders o
left join user u on o.user_id=u.id
</select>
5.2一对多查询
需要在User.java添加List ordersList;
<!-- 一对多关联查询 -->
<resultMap type="User" id="user">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<!-- 一对多 -->
<collection property="ordersList" ofType="Orders"><!-- ofType指定泛型 -->
<id column="id" property="id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
</collection>
</resultMap>
<select id="selectUserList" resultMap="user">
select o.id,o.user_id,o.number,o.createtime,u.username from user u
left join orders o on o.user_id=u.id
</select>
6. Mybatis整合spring
6.1配置头
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<!-- 配置SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml" />
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
6.2传统Dao开发
<!-- Mybatis的工厂 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入连接池 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 核心配置文件的位置 -->
<property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
</bean>
<!-- Dao -->
<bean id="userDao" class="com.heima.dao.UserDaoImpl">
<!-- 注入工厂 -->
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean"></property>
</bean>
6.3Mapper动态代理开发
<!-- Mapper动态代理开发
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean"></property>
<property name="mapperInterface" value="com.heima.mapper.UserMapper"></property>
相当于:
//创建sqlSession
SqlSession openSession = build.openSession();
//SqlSession帮我生成一个实现类(给接口)
UserMapper mapper = openSession.getMapper(UserMapper.class);
</bean>-->
<!-- Mapper动态代理开发 扫描 自动注入工厂-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 基本包 -->
<property name="basePackage" value="com.heima.mapper"></property>
</bean>
6.4SpringTest
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//UserMapper mapper = (UserMapper) ac.getBean("userMapper");Mapper动态代理开发
UserMapper mapper = ac.getBean(UserMapper.class);//Mapper动态代理开发 扫描 自动注入工厂
User user = mapper.findUserById(10);
System.out.println(user);
7.Mybatis逆向工程
使用官方网站的Mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和Mapper映射文件
导入逆向工程Project,修改配置运行即可得到
注意:
- 逆向工程生成的代码只能做单表查询
- 不能在生成的代码上进行扩展,因为如果数据库变更,需要重新使用逆向工程生成代码,原来编写的代码就被覆盖了。
- 一张表会生成4个文件
结语
上述基本就是Mybatis入门所有的内容啦,如果这篇文章对你有帮助的话,动动小手点个赞吧🤭