1.JDBC的缺陷是什么?
1.代码冗余。加载驱动,创建连接对象,数据库操作对象,关闭对象等操作对应每个数据库操作都是一样的。
2.对应ResultSet结果集,我们要遍历他然后手工创建Java对象装入集合,比较麻烦。
3.数据库操作和业务代码混合。
2.Mybatis是什么?为什么要放弃JDBC而使用Mybatis?
Mybatis可以看做增强版jdbc,底层也是用jdbc操作数据库但Mybatis帮我们减轻了开发的复旦。不需要我们重复编写创建Connection,Statement,PreparedStatement,ResultSet对象的代码。不需我们关注这些对象的关闭,自动帮我们关闭。还有自动将ResultSet中的记录封装成java对象的集合返回给我们。让开发者专注于SQL语句的编写。
3.传统Dao方式使用Mybatis操作数据库的基本步骤(未使用动态代理为我们创建Dao接口实现类对象)
1.加入依赖:mybatis依赖,数据库驱动。
2.创建Dao接口,定义操作数据库的方法。
3.创建Dao接口的同名Sql映射文件(Mapper文件)。
4.创建Dao接口实现类:方法中获得SqlSession对象操作数据库。
5.创建主配置文件:配置数据库数据源,mapper文件的位置等。
public interface StudentDao {
List findAll();
}
select name,age from student;
public class StudentDaoImpl implements StudentDao {
@Override
public List findAll() {
String path="mybatis.xml";
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(stream);
SqlSession sqlSession = factory.openSession();
List list = sqlSession.selectList("com.zhaojisu.dao.StudentDao.findAll");
sqlSession.close();
return list;
}
}
public class test {
@Test
public void testSelectAsList(){
StudentDao studentDao=new StudentDaoImpl();
List all = studentDao.findAll();
all.forEach(a->{
System.out.println(a);
});
}
}
4.SqlSessionFactoryBuilder类 SqlSessionFactory 接口 SqlSession 接口
SqlSessionFactoryBuilder类 :SqlSessionFactory 的 创 建 , 需 要 使 用 SqlSessionFactoryBuilder 对 象 的 build() 方 法 。 由 于 SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将 该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。
SqlSessionFactory 接口:SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用 只需要一个该对象即可。创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。
➢ openSession(true):创建一个有自动提交功能的 SqlSession
➢ openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
➢ openSession():同 openSession(false)
SqlSession 接口:SqlSession接口对象用于对数据库进行操作。一个SqlSession对应一次数据库会话,一次会话以SqlSession的创建开始,以SqlSession的关闭结束。SqlSession不是线程安全的,每次使用完都需要关闭它。
5. 传统 Dao 开发方式的分析
从上面我们自己写的Dao接口实现类中发现,实现类其实没有干什么实质性的工作,核心就通过SqlSession接口的API,根据mapper文件中的namespace和id定位某条sql语句操作数据库。若Dao接口中有多个方法,实现类方法中大部分代码都是冗余的,处理SqlSession调用的API不同。所以可以使用Myabtis动态代理方式为我们创建Dao接口的实现类对象,省略了Dao接口实现类的编写过程,让开发人员关注Mapper文件中Sql语句的编写。
6. SqlSession.getMapper(Class
public class AppTest {
@Test
public void t() {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis.xml");
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession sqlSession = factory.openSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
System.out.println(mapper);
List all = mapper.findAll();
all.forEach(a->{
System.out.println(a);
});
}
}
方法返回Dao接口实现类的对象。类型为org.apache.ibatis.binding.MapperProxy。采用的是jdk动态代理的方式。mybatis根据传入的Dao接口的字节码,匹配所以mapper文件中的namespace。然后根据mapper文件中的sql语句创建Dao接口的实现类对象。
7.myabtis为我们创建Dao接口实现类的要求
1.Mapper文件中
标签中的namespace为Dao接口的全限定类名。 2.Mapper文件中
3.Dao接口中不能有重载方法的定义。
4.Dao接口名和Mapper文件名最好一致,方便我们自己对应。
8.mybatis传参
1.一个普通类型的参数:#{任意名}
接口中的方法:Student findOne(String name);
sql:
select * from student where name=#{aaaa}
2.多个参数:使用@Param注解
接口中的方法:Student findOne2(@Param("name") String name, @Param("age") Integer age);
sql:
select * from student where name=#{name} and age=#{age}
3.多个参数:使用Java对象传参 #{对象的属性名}
接口中的方法:Student findOne3(Student student);
sql:
select * from student where name=#{name} and age=#{age}
4.按位传参:#{arg0} #{arg1}.....
5.Map
集合传参: #{key}
9. ${}
${}表示字符串替换。使用的是Statement对象。有sql注入的风险。通常用来替换表名或者列名。
10. #与$的区别 面试题
1.#是站位符,底层采用的是PreparedStatement。#{}编译之后变成?。效率高。
2.使用#避免了sql注入,比较安全。
3.$表示字符串替换,底层采用的是Statement。先将${}表示的字符串拼接然后执行sql。效率低。
4.使用$有sql注入的风险,在保证安全的情况下,有时需要进行sql注入。
5.$经常用来替换表名,列名。
11.resultType
返回的java对象类型。mybatis在封装结果时,先调用类的无参构造然后将查出的字段的值赋给同名属性。没有则不赋值。
12. resultMap
用于当表中字段与类的属性名不一致时,手动将字段对应属性。
主键字段用id标签,其他用result标签
13 动态Sql:使用动态Sql时,传入的参数要用java对象
if容易造成语法错误,所以在后面加一个不影响查询结果且恒成立的条件。
.... 使用where标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。需要注意的是,第一个if标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错, 系统会将多出的 and 去掉。但其它中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错。
resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
where id in
item="stuid" separator=",">
#{stuid}
foreach标签一般用于in子句。
collection表示参数中的数组或List集合。
item表示数组或集合中的一个元素。
open表示循环开始前的字符
close表示循环结束后的字符
spearator表示元素之间的字符。
用于sql语句的复用
14.PageHelper
PageHelper.startPage(PageNum,PageSize);分页效果只对该方法执行后的第一条查询产生影响。
PageHelper分页过程:
先count(*)计算查询出来的全部记录数,然后在sql语句后面加入limit ?,?进行分页。



