一、使用注解开发
1、面向接口编程:根本原因在于“解耦”,可拓展,提高复用。
<!--绑定接口-->
<mappers>
<mapper class="com.hr.dao.UserMapper"/>
</mappers>
@Select("select * from user")
List<User> findAll();
SqlSession sqlSession = MybatisUtils.getSqlSession();
//底层用反射机制
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
本质:通过反射机制实现;
底层:动态代理;
二、Mybatis的执行流程
1、Resources获取加载全局配置文件;
//1、获取sqlSessionFactory对象
static {
try {
String resouce = "mybatis-code.xml";
InputStream inputStream = Resources.getResourceAsStream(resouce);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
2、实例化SqlSessionFactoryBuilder;
3、通过XMLConfigBuilder来解析配置文件流;
4、所有的配置信息再放到Configuration 对象里;(new SqlSessionFactoryBuilder().build(inputStream)在build中
)
5、SqlSessionFactory实例化(已经携带了以上对象)
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
}
}
return var5;
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
6、trasactional事物管理;
7、创建执行器executor;(它会执行mapper,通过反射加载出来类的信息,把SqlSession的执行器套用进去,执行sql)
8、创建SqlSession;(为了实现CRUD,事物出现问题,会回滚到事物管理,执行成功再提交事物,最后关闭SqlSession,未执行成功又会回滚到事物管理)
三、用注解实现CRUD
public static SqlSession getSqlSession(){
//设置为真,不用去手动SqlSession.commit();
return sqlSessionFactory.openSession(true);
}
@Select("select * from user")
List<User> findAll();
//查单个,基本数据类型和String需要加上,多个参数一定要加@Param注解,引用对象不用加
@Select("select * from user where id = #{id}")
User findOne(@Param("id") int id);
@Insert("insert into user (name,pwd) values (#{name},#{password})")
int add(User user);
@Delete("delete from user where id =#{id}")
int delete(int id);
@Update("update user set name = #{name},pwd = #{password} where id = #{id}")
int update(User user);
关于@Param注解:
- 基本类型的参数或者String要加上
- 引用类型不需要加;
- 如果只有一个基本类型,可以忽略,但是最好加上;
- 在sql中引用的就是@Param()中设定的属性名
“# ”和 “$”的区别::
- 使用#{} 相当于在原来的sql语句字段上加了双引号" ",可以很大程度上防止sql注入;
- 使用${}引入数据会直接显示在生成的sql语句中,无法防止sql注入;
四、多对一处理(相当于站在学生的角度,主要查学生的信息)
1、多个学生,对应一个老师;
- 对于学生这边而言,关联{association},多个学生,关联一个老师【多对一】
- 对于老师而言,集合{collection},一个老师,有很对学生【一对多】
2、多对一,通常在多的那一方关联,private一个关联的对象
3、按照查询嵌套处理(子查询)
<!--在查询完所有学生,就已经将tid作为结果传给 #{id}查询老师了-->
<select id="findAllStudentAndTeacher" resultMap="studentAndteacher">
select * from student
</select>
<resultMap id="studentAndteacher" type="Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="findAllTeacher"/>
</resultMap>
<!--在这里把"#{id}"换成"#{tid}"也是一样的结果-->
<select id="findAllTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
4、按照结果嵌套处理:通过结果做映射
<-- 在这里 column对应的是sql里面的别名,一一对应--/>
<select id="findAllStudentAndTeacher2" resultMap="studentAndteacher2">
select s.id sid,s.name sname,t.name tname from student s,teacher t where t.id=s.tid
</select>
<resultMap id="studentAndteacher2" type="Student">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
五、一对多处理(在案例中站在老师的角度,主要查的是有关老师的信息)
1、按照结果嵌套查询:
//获取指定老师下的所有学生和老师的信息
List<Teacher> findAllTeacherAndStudent(@Param("tid") int id);
<select id="findAllTeacherAndStudent" resultMap="AllTeacherAndStudent">
select t.id tid,t.name tname,s.id sid,s.name sname,s.tid stid from teacher t,student s where t.id=s.tid
</select>
<resultMap id="AllTeacherAndStudent" type="Teacher">
<id property="id" column="tid"/>
<result property="name" column="tname"/>
<!--javatype:指定属性的类型,ofType相当于javaType,但是ofTyPE是修饰集合的,集合中的泛型信息用oftype-->
<collection property="studentList" ofType="Student">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="stid"/>
</collection>
</resultMap>
2、按照查询嵌套查询:
<select id="findAllTeacherAndStudent2" resultMap="AllTeacherAndStudent2">
select * from teacher where id = #{tid}
</select>
<resultMap id="AllTeacherAndStudent2" type="Teacher">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--老师里面的id-->
<collection property="studentList" column="id" javaType="ArrayList" ofType="Student" select="findAllStudentByStudentId"/>
</resultMap>
<select id="findAllStudentByStudentId" resultType="Student">
select * from student where id = #{tid}
</select>
3、小结:
-
关联:association【多对一】
-
集合:collection【一对多】
-
javaType:指定实体类中属性的类型
-
ofType:用来指定映射到list或者集中的pojo类型、泛型中的约束类型;
面试高频:
- Mysql引擎、
- InnoDB底层原理、
- 索引、
- 索引优化