框架
ORM对象关系映射
MyBatis是ORM框架,作用是以面向对象的方式完成数据库操作。ORM框架有MyBatis、Hibernate、SpringJPA。
原始JDBC的缺陷:
MyBatis:
介绍:
小结:MyBatis封装了JDBC,是Java用来操作数据库的框架,只需要关注SQL语句本身,且能自动实现Java类和数据库的映射。
使用步骤:
1.准备数据
2.导jar包,添加到路径
3.src目录下创建映射配置文件、核心配置文件
映射配置文件:
第一行文档声明,第二行约束(什么是约束:配置了mybatis的约束那么写的文档不符合mybatis的规则就会报错):
mapper标签(核心根标签):
配置SQL语句的标签:
结果封装成Student对象,resultType就是student;
参数是student对象的一个属性,parameterType就是该属性类型,
参数是student对象的多个属性,要传递一个student对象,parameterType就是student。
核心配置文件:
第一行第二行依然是文档声明、约束;
第三行是核心根标签:
这里引入数据库连接的配置文件,下面配置数据库环境时用$ { 键名 }来获取连接配置,而不会写死。
起别名,在映射配置文件中就可以不用写全类名,写别名就行了。MyBatis自带的别名:int,string,double,long,boolean。
起别名<package>标签指定整个配置文件的全类名的包名,设置<package>标签后写类名就不用写全类名了,只写类名小写。
environments标签里可以有多个environment标签,<environments default="mysql">指定默认环境配置是id为"mysql"的environment标签。
MyBatis测试:
DaoImpl类的findAll()方法:
Resources用的是org.apache.ibatis.io包下的,因为MyBatis前身名字叫ibatis:
执行SQL语句时,通过 名称空间.标签id 找到SQL语句。
MyBatis相关API:
true开启自动提交事务后,增删改涉及到事务操作就不需要我们自己来了。
映射配置文件
手动提交事务:
自动提交事务:
核心配置文件
配置数据库环境、引入映射配置文件、配置一些工具。
LOG4J
LOG4J配置文件只关注第一条,输出级别,debug及以上的级别都输出,stdout标准输出(控制台)。
MyBatis接口代理方式实现Dao层
1.名称空间和Dao接口全类名相同:
2.SQL标签id和Dao接口方法名相同:
3.SQL标签parameterType属性和Dao接口方法参数相同:
4.SQL标签resultType属性和Dao接口方法返回值:
实现Service层
传统方式是Service层调用Dao层实现类,现在没有Dao层实现类了,所以Service层要重新写:
@Override
public List<Student> selectAll() {
List<Student> list = null;
SqlSession sqlSession = null;
InputStream is = null;
try{
//1.加载核心配置文件
is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();
//5.通过实现类对象调用方法,接收结果
list = mapper.selectAll();
} catch (Exception e) {
} finally {
//6.释放资源
if(sqlSession != null) {
sqlSession.close();
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//7.返回结果
return list;
}
注意:用MyBatis的接口代理来获取动态代理对象(Dao接口实现类对象),调用操作方法。
使用JDK的动态代理技术实现接口代理。
动态SQL
<if>
为了应对查询条件不确定的情况。
<where>标签用来代替WHERE关键字,<if>标签如果test满足了,就会把标签内的SQL语句拼接上:
这样传入一个domain对象,不作为查询条件的属性不赋值(默认null),就可以实现任意查询条件查询。
MyBatis没有if-else结构,有
<choose>内是个整体,<when><otherwise>相当于if-else,如果想嵌套,那么应该把<choose>一个整体嵌套在<when>或者<otherwise>里。
<foreach>
为了应对传入多个id查询多条数据。
参数是list,是id的集合;
<foreach>标签的属性:collection是要遍历的集合,
open是要拼接的SQL片段的开始,close是结束,
item="id"是collection里拿出的元素赋值给<foreach>内的局部变量id,
separator是拼接上的分隔符。
<sql>
抽取sql语句,重复使用。(就像模板)
抽取:
使用:
MyBatis多表操作
一对一
在任一表中设置外键。如IDCard表和Person表,在IDCard表中存储外键pid记录对应Person的id。
<select>标签,因为现在涉及两个表,不能用resultSet指定一个映射的实体类,要用resultMap。
现在是card和person一对一,card设置外键,实体类中card中保存person对象,即person类是被包含的类。
<resultMap>标签,id是唯一标识,用来被<select>标签引用,type是映射的实体类(存有外键的)。
<id>标签是card表主键的映射关系,column是列名,property是card实体类属性名。
<result>标签是card表非主键的映射关系,column是列名,property是card实体类属性名。
<association>标签是被包含类(person被包含在card里)的映射关系,property是被包含类在card类中的属性名,javaType是被包含类的类名。(如果Card类里有个Person p,那么property="p",javaType="person");
<id>是外键表的主键映射关系,column是列名,property是person实体类属性名。
<result>标签是card表非主键的映射关系,column是列名,property是person实体类属性名。
一对多
一个班级对应多个学生,学生表中有外键记录班级的id,注意:学生类中没有班级类对象作为属性,班级类中有学生类对象的集合,因此一对多关系里面,多的一方作为被包含类。
和一对一的区别仅在于设置被包含类映射的标签换成了<collection>,property是班级类里学生集合的属性名,resultMap
多对多
一个学生对应多个课程,一个课程也对应多个学生,增加中间表实现多对多。注意:采取课程类作为被包含类,学生类里有课程类对象的集合。
映射配置文件中的实现方式和一对多完全一样,只不过查询语句变了、一的一方变成学生类、多的一方变成课程类。
注解开发代替映射配置文件
使用映射配置文件的缺点是麻烦,还要编写映射配置文件,<mapper>的namespace还要和Dao层接口的全类名相同。
使用注解大好处是简化开发操作,省去了编写映射配置文件。
核心配置文件
这里用引入映射配置文件了,而是指定Dao层接口的包名。
带注解定义接口方法
Seivice层实现方法
方法传入stu对象,会从里面提取id、name、age等属性:
注解多表操作
一对一
一个card对应一个person,一个person也对应一个card,card表中有外键pid,Card类中有Person成员变量。
核心配置文件配置映射关系:(可以写Dao层接口所在目录的父目录,只要其下有那些映射接口,就都能找到)
Dao层card接口,带注解声明方法:
因为是多表操作,所以没法完成自动映射,除了@Select注解还要写@Results注解,@Results是个父注解,参数是个数组,包含多个子注解,每个子注解指定card类每个成员变量的映射关系。
column是列名,property是成员变量名,和映射配置文件的写法类似。
Card类里的Person成员变量(被包含类)的映射就复杂一些,property是被包含对象的变量名,javaType是被包含对象的类型,column是外键名(即根据查出的card表中的pid字段再去查询person表),one是被包含对象,one = @one是一对一注解的固定写法,select指定再调用哪个接口方法去映射出一个Person对象。
刚才指定的接口在这:
这里只设计单表操作,因此只写@Select,能自动映射。
Service层方法:
一对多
一个学生对应一个班级,一个班级对应多个学生,学生表中有外键记录班级id,班级类中有学生类集合记录所有学生。
Dao层映射接口:只需要把javaType换成List.class,对另一个表查询用many = @Many:
Service层方法:
多对多:
一个学生对应多个课程,一个课程也对应多个学生,添加中间表实现多对多。学生类里有课程类集合。
Dao层student映射接口:和一对多完全一样,因为多对多本来就是通过和中间表的一对多来实现的。
查询语句如果直接写SELECT * FROM STUDENT;的话,会把没有课程的学生也查询出来,其实我们只看有课程的学生,因此用多表查询限制一下。
Dao层course映射接口:
根据student的id调用此方法查询对应的课程,用的是课程表和中间表多表查询:
Service层方法:
ORM框架缓存:
一级缓存:SQLSession级缓存,默认开启,记录和数据库交互的session会话的数据,SQLSession生命周期很短,在交互玩一次就完了,