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.反射机制的优缺点
优点: