一、Mybatis和Jdbc联系和区别
1、jdbc有很多重复性的代码(贾琏欲执事 ), mybatis处理参数或者返回值
2、mybatis维护sql更方便,都写到配置文件,jdbc的sql需要写到类里面,比较麻烦
3、jdbc底层没有性能 ,需要自己实现,mybatis有缓存,一般不用
4、mybatis可以移植数据库,比较方便(mysql),jdbc 比较麻烦
二、mybatis和jpa的优缺点?
1、jpa和mybatis都是orm框架,都是持久层;
jpa 性能不好控制,如果一个表数据太大,不适合使用jpa操作;
jpa能够自动生成sql ;jpa一般适合中小型的项目。
2、mybatis 是半自动的orm的框架,sql 我们可以灵活控制,有专门的配置文件去写sql,统一管理的sql,XxxxMapper.xml (crud),对应参数封装,返回的也做的一些处理 ;mybatis 它是轻量级的框架,可以很灵活的使用,特别你的sql要求比较高的,mybatis 最适合;redis–处理性能比较NB ;
三、#{}与${}的区别
1、#{} 只是替换?,相当于PreparedStatement使用占位符去替换参数,可以防止sql注入。
2、${} 是进行字符串拼接,相当于sql语句中的Statement,使用字符串去拼接sql;$可以是sql中的任一部分传入到Statement中,不能防止sql注入。
3、使用${} 去取出参数值信息,需要使用${value}
4、#{} 只是表示占位,与参数的名字无关,如果只有一个参数,会自动对应。
四、MyBatis使用步骤总结
1、配置mybatis-config.xml 全局的配置文件 (1、数据源,2、外部的mapper)
2、创建SqlSessionFactory
3、通过SqlSessionFactory创建SqlSession对象
4、通过SqlSession操作数据库 CRUD
5、调用session.commit()提交事务
6、调用session.close()关闭会话
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的主要功能就是写sql
mapper:根
namespace:命令空间 (用来确定唯一) 以前这个是可以不加的,现在必需加
namespace的值,规则:映射文件XxxMapper.xml所在的包+domain类名+Mapper
-->
<mapper namespace="cn.chenxin.domain.UserMapper">
<!--
select : 这里面写查询语句
id:用来确定这条sql语句的唯一
以后我们确定唯一,也就是找sql语句 : namespace +.+ id
例: cn.chenxin.mybatis.day1._1_hello.ProductMapper.get
parameterType : 传入的参数类型 long:大Long _long:小long (具体的对应请参见文档)
resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
-->
<select id="queryOne" parameterType="long" resultType="cn.chenxin.domain.User">
select * from t_user where id = #{id}
</select>
<!--条件查询-->
<select id="queryOne01" parameterType="UserQuery" resultType="cn.chenxin.domain.User">
select * from t_user
<where>
<if test="id != null">
id = #{id}
</if>
<if test="name !=null">
and name = "${name}"
</if>
</where>
</select>
<select id="queryAll" resultType="cn.chenxin.domain.User">
select * from t_user
</select>
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id" >
insert into t_user (name) value (#{name})
</insert>
<!--批量保存-->
<insert id="batchSaving" parameterType="java.util.ArrayList">
insert into t_user (name) values
<foreach collection="list" item="item" separator=",">
(#{item.name})
</foreach>
</insert>
<update id="update" parameterType="cn.chenxin.domain.User" >
update t_user set
name = #{name}
where id = #{id}
</update>
<delete id="delete" parameterType="long">
delete from t_user where id = #{id}
</delete>
<!--批量删除-->
<delete id="batchDelete" parameterType="list">
delete from t_user where id in
<foreach collection="list" index="index" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
<!--批量修改-->
<update id="batchUpdate" parameterType="map">
update t_user set name = #{newName} where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</update>
</mapper>
Mybatis-config.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>
<!-- 环境们 (很多环境的意思)
default:默认使用哪一个环境(必需对应一个环境的id)
-->
<properties resource="jdbc.properties"></properties>
<!--别名-->
<typeAliases>
<!--单个类-->
<!--<typeAlias type="cn.chenxin.domain.User" alias="user"></typeAlias>-->
<!--包名-->
<package name="cn.chenxin.domain"/>
<package name="cn.chenxin.query"/>
</typeAliases>
<environments default="development">
<!--
一个环境 id:为这个环境取唯一一个id名称
-->
<environment id="development">
<!--
事务管理 type:JDBC(支持事务)/MANAGED(什么都不做)
-->
<transactionManager type="JDBC" />
<!-- 数据源, 连接池 type(POOLED):MyBatis自带的连接池 -->
<dataSource type="POOLED">
<!-- 连接数据库的参数 -->
<property name="driver" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 这个mappers代表的是相应的ORM映射文件 -->
<mappers>
<mapper resource="cn/chenxin/domain/UserMapper.xml" />
</mappers>
</configuration>
五、使用映射器Mapper
步骤:
1、定义一个接口 UserMapper
public interface UserMapper {
public List<User> queryAll();
}
2、写配置文件
<mapper namespace="cn.chenxin._01_mapper.UserMapper">
<select id="queryAll" resultType="cn.chenxin._01_mapper.User">
select * from t_user
</select>
</mapper>
3、测试类
public class TestMapper {
@Test
public void test() throws Exception{
SqlSession sqlSession = MybatisUtil.INSTANCE.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.queryAll());
}
}
六、高级查询
1、模糊查询:"%${name}%"或concat(’%’,#{name},’%’)
2、特殊字符”>”和“<”,用>或< 或者<![CDATA[ … ] ]>
<select>
select * from t_user
<where>
<if test="name!=null and name!=''">
<!-- name like "%${name}%" -->
name like concat('%',#{name},'%')
</if>
<if test="maxAge!=null and minAge!=null ">
<!-- and age > #{minAge} and age < #{maxAge} -->
<![CDATA[and age > #{minAge} and age < #{maxAge}]]>
</if>
</where>
</select>
七、结果映射
问题:解决类字段与数据库列名不一样的情况(User类属性为password,表中字段为psw)
1、采用取别名
<select id="query01" resultType="cn.chenxin._03_resultMap.User">
select u.id,u.name,u.age,u.psw password from t_user u
</select>
2、结果映射
<resultMap id="UserResult" type="cn.chenxin._03_resultMap.User">
<id property="id" column="id"/>
<result property="password" column="psw"/>
</resultMap>
<select id="queryAll" parameterType="cn.chenxin._03_resultMap.UserQuery" resultMap="UserResult">
</select>
八、关联对象
1、manyToOne ,处理一方
嵌套结果:
<resultMap id="UserResult" type="cn.chenxin._04_manyToOne.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="password" column="psw"/>
<!--property为User中一方的字段-->
<association property="dept" javaType="cn.chenxin._04_manyToOne.Department">
<result property="name" column="dept"/>
</association>
</resultMap>
<select id="queryAll" parameterType="cn.chenxin._04_manyToOne.UserQuery" resultMap="UserResult">
select u.id,u.name,d.name dept from t_user u join t_department d on u.dept_id = d.id
<where>
<if test="name!=null and name!=''">
<!-- name like "%${name}%" -->
u.name like concat('%',#{name},'%')
</if>
<if test="maxAge!=null and minAge!=null ">
<!-- and age > #{minAge} and age < #{maxAge} -->
<![CDATA[and u.age > #{minAge} and u.age < #{maxAge}]]>
</if>
</where>
</select>
嵌套查询:
<resultMap id="UserResult01" type="cn.chenxin._04_manyToOne.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--property:User类属性 column:查询出来的dept_id列 -->
<association property="dept" column="dept_id" select="DeptResult" javaType="cn.chenxin._04_manyToOne.Department"/>
</resultMap>
<select id="query01" resultMap="UserResult01" >
select u.id,u.name,u.dept_id from t_user u
</select>
<select id="DeptResult" parameterType="long" resultType="cn.chenxin._04_manyToOne.Department">
select * from t_department where id = #{dept_id}
</select>
2、oneToMany,处理多方
嵌套结果:
<!--方式一:嵌套结果 必须加order by,否则数据会缺失;分页:不能分出两个部门-->
<resultMap id="DeptResult" type="cn.chenxin._05_oneToMany.Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="users" javaType="arrayList" ofType="cn.chenxin._05_oneToMany.User" >
<id column="uid" property="id"/>
<result column="uname" property="name"/>
<result column="psw" property="password"/>
</collection>
</resultMap>
<select id="queryAll" resultMap="DeptResult" >
select d.id,d.name,u.id uid,u.name uname,u.psw psw
from t_department d
join t_user u
where d.id = u.dept_id
order by d.id
<!-- limit 0,5 -->
</select>
嵌套查询:
<resultMap id="DepartmentResult" type="cn.chenxin._05_oneToMany.Department">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--根据部门的id去查询相关员工-->
<collection property="users" column="id" ofType="cn.chenxin._05_oneToMany.User" select="UsersSelect"/>
</resultMap>
<select id="query01" resultMap="DepartmentResult">
select d.id,d.name from t_department d
</select>
<select id="UsersSelect" parameterType="long" resultType="cn.chenxin._05_oneToMany.User">
select * from t_user where dept_id = #{id}
</select>
九、集成SSM
applicationContext.xml中加配:
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 把所有的mapper.xml都配置-->
<property name="mapperLocations" value="classpath:cn/chenxin/mapper/*Mapper.xml"/>
<!--配置别名-->
<property name="typeAliasesPackage" value="cn.chenxin.domain"/>
</bean>
<!-- mybatis会产生mapper实现类 交给spring管理
扫描cn.chenxin.ssm.mapper包 下面的所有的接口
spring事务 多个操作方法 事务传播机制
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.chenxin.mapper"/>
</bean>
<!--注入mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--只要扫描到该包下所有的接口,我都使用代理模式进行实现-->
<property name="basePackage" value="cn.chenxin.mapper"/>
</bean>