回顾
-
动态代理
-
如何创建代理对象
接口 代理对象 = (接口) Proxy.newProxyInstance(类加载器,new Class[]{接口.class},new InvocationHandler(){ // 代理对象任意方法调用时,都会进入 invoke public Object invoke(Object p, Method method, Object[] args) throws Throwable{ // 增强或是执行真实对象的方法 if(method.getName().equals("增强的方法名")) { // 增强的逻辑 } else { // 反射执行真实对象的方法 method.invoke(真实对象, args); } } });
-
代理对象如何、在哪里调用真实对象的方法、并提供增强?
-
-
mybatis - api
-
SqlSessionFactory 如何创建?有哪些常见方法
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(配置文件的输入流); factory.openSession();// 手动控制事务 factory.openSession(true); // 自动提交事务
-
SqlSession 有哪些常见方法
selectList("namespace+sql id", 参数对象); selectOne("namespace+sql id", 参数对象); insert("namespace+sql id", 参数对象); update("namespace+sql id", 参数对象); delete("namespace+sql id", 参数对象); commit(); rollback();
-
-
mapper 映射文件
<mapper namespace="名称空间"> <select id="标识" resultType="结果类型" parameterType="参数类型"> sql 语句 #{ } </select> <insert useGeneratedKeys="true" keyProeprty="主键对应的属性名"></insert> </mapper>
- 如果是简单类型,
#{ }
中怎么写,随便写 - 如果是 map 类型,
#{ }
中怎么写,写 key - 如果是自定义实体类型,
#{ }
中怎么写,写属性名
- 如果是简单类型,
-
核心配置文件
- 配置数据库连接信息
- 配置有哪些映射文件
- 配置实体类别名
今日内容
1. 接口代理
- namespace 必须和 接口全类名一样
- sql 语句 id 必须和 接口中的方法名一样
- 参数和返回值要一致
接口Mapper mapper = sqlSession.getMapper(接口Mapper.class); // 返回就是一个代理对象
通过调用接口中的方法,间接执行映射文件中 sql
接口代理方式,底层是用 jdk 的动态代理技术,根据接口的方法调用,去查找映射文件中相应的 sql,然后执行
-
mapper xml 映射文件建议与 mapper 接口放在同一路径下,并且名字一样(映射文件名与接口名一样)
<mappers> <!-- 原始写法 --> <!-- <mapper resource="com/itheima/mapper/StudentMapper.xml"></mapper> <mapper resource="com/itheima/mapper/TeacherMapper.xml"></mapper>--> <!-- 简化写法: 直接写接口和映射文件的包名, 可以找到此包下所有映射文件和接口 --> <package name="com.itheima.mapper"/> </mappers>
-
mybatis 接口中方法不能有重名,因为 映射文件中 id 是不能重名的
-
接口的参数一般建议写一个参数(多个参数可以封装到一个map集合中),如果要写多个参数,那么需要注解
// 解决方法1:多个参数可以封装到一个map集合中 // map n 姓名 a 年龄 // List<Student> findByNameAndAge(Map<String,Object> map); // 解决方法2:使用 @Param 注解来指明多个参数,就不需要在 sql 标签中加入 parameterType 属性 List<Student> findByNameAndAge( @Param("n") String name, @Param("a") Integer age);
2. 动态 sql (*)
Student stu …
stu.setName(“张三”);
select * from student
where name=?
关于 if 标签的注意事项:
<if test="条件"> sql片段 </if>
- 除了 id 以外的其它属性,建议使用包装类型,包装类型才可以用 null 来判断
- where 标签的作用:会删除拼接后多余的 and
- 如果是字符串类型的参数
<if test="name!=null and name != '' ">
才算成立,因为页面上传递过来的字符串参数是一个"" 而不是 null
<forEach collection="list|array"
open="开始" close="结束" separator="分隔符" item="临时变量名">
#{临时变量名}
</forEach>
<sql id=""></sql>
<include refid=""></include>
3. 分页(*)
page 页号
siez 记录数
起始索引 = (page-1) * size
select * from 表 limit 起始索引, 此页记录数
PageHelper.startPage(页号, 记录数); // 先调用,才会生效
mapper.查询方法(); // select * from 表 limit ... 底层是给正常 sql 添加了 limit 语句来实现的
一共有几页
总记录数 记录数
8 3 8/3 =2 +1
9 3 9/3=3
获取分页参数
new PageInfo(查询list结果); // 获取总记录数、总页数...
4. 多表(难点)
连接查询
- 一对一
建立查询结果与实体类对应关系
select cid, number, pid, name, age
<resultMap id="唯一表示" resultType="Card">
<id column="列 cid" property="属性 id"/>
<result column="列 number" property="属性 number"/>
<association property="p" javaType="Person">
<id column="列 pid" property="属性 id"/>
<result column="列 name" property="属性 name"/>
<result column="列 age" property="属性 age"/>
</association>
</resultMap>
class Card {
int id;
String number;
Person p;
}
class Person {
int id;
String name;
Integer age;
}