1.#{} 和${}区别
#{} 是占位符,是采用编译方式向sql中传值,可以防止sql注入,如果往sql中传值,使用#{}
${} 是将内容直接拼接到sql语句中,一般不用于向sql中传值,一般用于向sql中动态传递列名。
区别:
1.底层实现不同
#{} 采用预编译方式 可以防止sql注入 更加安全
${} 采用字符串拼接,直接将值拼接到sql中
2.使用场景不同
#{} 一般用于向sql中的列传值
${} 一般用于sql动态传递列名 例如,排序时order by 后面的列名是可以改变的。例如,select后面的列名也可以自由选择
2.特殊处理定义 resultMap
(1)定义resultMap
<resultMap id="studentMap" type="Student">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
</resultMap>
<select id="findStudentFindById" resultMap="studentMap">
select
s.id,
s.num,
s.name,
s.gender,
m.name mname
from student s inner join major m on s.majorid=m.id where s.id=#{id}
</select>
3.多表关联处理结果集
- 嵌套结果映射 – 关联可以是
resultMap元素,或是对其它结果映射的引用
- 嵌套结果映射 – 集合可以是
resultMap元素,或是对其它结果映射的引用
4.动态SQL
1.if
<select id="teachers" resultType="Teacher">
select * from teacher
<where>
<if test="num!=null">
num= #{num}
</if>
<if test="name!=null">
and name= #{name}
</if>
<if test="gender!=null">
and gender= #{gender}
</if>
</where>
语法:<if test=""></if>
注意:test属性成立,执行if标签体,不成立就不执行
2.where
<select id="teachers" resultType="Teacher">
select * from teacher
<where>
<if test="num!=null">
num= #{num}
</if>
<if test="name!=null">
and name= #{name}
</if>
<if test="gender!=null">
and gender= #{gender}
</if>
</where>
</select>
语法:<where></where>
注意:当where标签中的if语句有条件成立时, 就会动态的添加where 关键字, 还可以动态删除where 紧跟着的关键字,例如 and or
3.trim
<select id="teachers" resultType="Teacher">
select * from teacher
<trim prefix="where" prefixOverrides="and| or">
<if test="num!=null">
num= #{num}
</if>
<if test="name!=null">
or name= #{name}
</if>
<if test="gender!=null">
and gender= #{gender}
</if>
</trim>
</select>
语法<trim prefix="where" prefixOverrides=""> </trim>
作用: trim 当判断条件成立时,可以自定义前缀关键字和后缀关键字
prefix="where"
prefixOverrides="and|or" 覆盖指定关键字
4.choose when otherwise
<select id="teachers" resultType="Teacher">
select * from teacher
<trim prefix="where" prefixOverrides="and| or">
<choose>
<when test="name!=null">
name=#{name}
</when>
<otherwise>
name='李老师'
</otherwise>
</choose>
</trim>
</select>
语法:
<choose>
<when test="判断条件">
执行的sql语句
</when>
<otherwise>
执行其他的sql语句
</otherwise>
</choose>
作用:MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句
5.set
<update id="updateTeacher" parameterType="Teacher">
update teacher
<set>
<if test="num!=null">
num=#{num},
</if>
<if test="name!=null">
name=#{name},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}
</update>
也可以用trim实现
<update id="updateTeacher" parameterType="Teacher">
update teacher
<trim prefix="set" suffixOverrides=",">
<if test="num!=null">
num=#{num},
</if>
<if test="name!=null">
name=#{name},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</trim>
where id=#{id}
</update>
6.foreach
array:

<delete id="deleteTeacher">
delete from teacher where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id} </foreach>
</delete>
List:

<select id="findTeacher" resultType="Teacher">
select
<foreach item="col" collection="list" separator=",">
${col}
</foreach>
from teacher
</select>
5.特殊符号处理
6.mybatis 一级缓存二级缓存
缓存作用:是为了减去数据库的压力,提高查询性能
缓存原理:是从数据库中查询出来的对象在使用完后不要销毁,而是存储在内存(缓存) 中,当再次需要获取该对象时,直接从内存(缓存)中直接获取,不再向数据库 执行 select 语句,从而减少了对数据库的查询次数,因此提高了数据库的性能。(先从缓存中查询数据,缓存中如果没有,去数据库查询,查询到后把数据放到缓存中,下次直接从缓存中获取)
1.mybatis一级缓存
(1)定义:在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调 用一个 Mapper 方法,往往只执行一次 SQL,因为使用 SelSession 第一次查询 后,MyBatis 会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新, 并且缓存没有超时的情况下,SqlSession 都会取出当前缓存的数据,而不会再 次发送 SQL 到数据库。(默认是SqlSession级别的,在同一个SqlSession中查询到数据先缓存到SqlSession对象中 第二次查询数据时,先从SqlSession中查询,如果有直接返回,没有,再去查询数据库)
(2)一级缓存生命周期:
开始于SqlSession创建
结束于SqlSession的关闭
如果执行期间新增,修改,删除操作,也会清空当前SqlSession对象中缓存数据。调用sqlSession.clearCache(),强制清空一切缓存数据。

2.mybatis二级缓存
(1)定义:二级缓存是 SqlSessionFactory 级别的,根据 mapper 的 namespace 划分区域的,相同 namespace 的 mapper 查询的数据缓存在同一个区域,如果使 用 mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二 级缓存区域是根据 mapper 划分。 每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数 据写入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。
作用: 二级缓存是SqlSessionFactory级别的,可以让多个SqlSession共享数据
注意:
* mybatis默认没有开启二级缓存,使用时需要配置开启。
* 如果开启二级缓存,当SqlSession关闭时,会将一级缓存数据存储到二级缓存中 , 其他的SqlSession就会从二级缓存中查询到之前的SqlSession数据。

(2)配置二级缓存设置
<1>启用二级缓存
在mybaits.xml文件中配置全局二级缓存开关

如下代码所示,当 cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。
3.mybatis架构

7.Java反射
在mybatis中,给了什么类型,mybatis就可以将结果封装映射到给定的类的对象中
<select id="findAdminByld" parameterType="int" resultType="Admin">
<select id="teachers" resultType="com.ffyc.mybatispro.model.Teacher">
框架需要只写一套程序,就可以处理给其的任意类,
框架是如何做到写一套程序,就可以处理任意类了?
以前已知类名的使用方式,可以看做是正向使用类.
框架需要对任意类处理时,只是知道类的名字,通过类的名字动态才去获取类中的信息.
把这种对类的使用方式,称为反向使用.
1.java反射概念及作用
2.java反射相关API
2.1.Class类(java.lang.Class)

(1)概念:Class类表示当前正在运行中的类和接口
注意;一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被 使用时都会创建一个Class对象;
Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本 信息。
(2)获得Class类的方法
2.2 Constructor类


获取Constructor的实例:
1.通过Class实例获得,Class类中定义了如下方法
(1)getConstructor() 获得指定的公共构造方法
(2).getConstructors();//获得所有公共的构造方法
(3).getDeclaredConstructor();//获得类中任意的构造方法(包含私有)
(4)getDeclaredConstructors();//获得类中所有的构造方法(包含私有)
2.Constructor类可以通过getXXX方法获得构造方法的基本信息.
2.3 Field类
Field类作用是获取到对象的成员变量

1.获得Field类实例:
public Field getField(String name)通过指定Field名字,返回 Field实例. 注意Field的访问权限
(1)getField("成员变量");//获得指定名称的公共的成员变量
(2)getFields() 获得所有的公共成员变量
(3)getDeclaredField( "成员变量t");//获得指定名称的成员变量,包含私有的
(4)getDeclaredFields( );//获得所有的成员变量,包含私有的
2.Field类的作用
2.4 Method类
1.获取Method类的实例:
8.反射案例
public class Test3 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//使用反射机制时,只知道类的名称(包名+类名)
String classname="com.ffyc.javaReflect.User";
/* String classname="com.ffyc.javaReflect.Car";*/
// 1.通过类名获得到类的Class对象
Class clazz= Class.forName(classname);
// 2.通过类的Class对象,创建对象
Object object=clazz.newInstance()
/*模拟从数据库拿到的数据*/
HashMap<String,String> map=new HashMap<>();
map.put("account", "admin");
map.put("password", "111");
Field[] fields=clazz.getDeclaredFields();//获得类中所有成员变量
for(Field field:fields){
field.setAccessible(true);//允许访问操作私有的属性
field.set(object,map.get(field.getName()) );
}
System.out.println(object);
}
}
2.自定义java对象转json工具类
类同上


public class JsonUtil {
public static String objectToJson(Object object) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
// 获取到类的Class对象
Class clazz=object.getClass();
String json="{";
//获取类中所有属性
Field[] declaredFields =clazz.getDeclaredFields();
for(Field field:declaredFields){
//生成属性get方法名字
String getmethod = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
//获得方法对象
Method method=clazz.getMethod(getmethod);
// 调用方法
String value=(String)method.invoke(object);
// 把属性名称和和值拼接成键值
json+=field.getName()+":"+value+",";
}
json=json.substring(0,json.length()-1);
json+="}";
return json;
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
User user=new User();
user.setAccount("admin");
user.setPassword("111");
Car car=new Car();
car.setName("bbb");
car.setColor("red");
System.out.println(JsonUtil.objectToJson(user));
System.out.println(JsonUtil.objectToJson(car));
}
}
9.反射机制的优缺点
优点:



















