一、Mybatis映射文件基本使用和参数传递
1.面试题:mybatis中#{}和${}的区别。
#{内容}:底层封装JDBC使用 ?占位符,并且可以使用下标进行取值。
${内容}:底层使用字符串拼接,并且不能使用下标取值,查找内容需要get/set方法。
2.Mybatis基本增删改查方式方法。
1.SQL映射文件中编写CRUD方法:
<insert id="insertOne" parameterType="Human">
insert human values(default,#{name},#{age},#{borthday})
</insert>
<delete id="deleteOne">
delete from human where id=#{0}
</delete>
<update id="updateOne" parameterType="Human">
update human set name=#{name},age=#{age}
where id = #{id}
</update>
2.调用CRUD方法的方式一:
1.直接通过session调用
selectOne()
、selectList()
、insert()
、delete()
、update()
等方法2.参数 statement(必填):
mapper命名空间+id
;他们都有多个重载,我们可以因此达到进行参数条件传递。 开发的时候推荐面向接口编程,我们不需要知道实现类的细节。
public void testCRUD1() {
Human human1 = new Human(null,"测试java",34,new Date());
Human human2 = new Human(12,"Linux",11,new Date());
SqlSession session = factory.openSession();
int delete = session.delete("cn.dao.TeacherDao.deleteOne",10);
int insert = session.insert("cn.dao.TeacherDao.insertOne",human1);
int update = session.update("cn.dao.TeacherDao.updateOne",human2);
session.commit();
session.close();
System.out.println("=========>"+delete);
System.out.println("=========>"+insert);
System.out.println("=========>"+update);
}
3.调用CRUD方法的方式二:(推荐)
1.面向接口编程:
简单的来说就是一组规范,一组约束;抽取客户需求的逻辑线,最后我们只要知道调用接口实现功能即可。
- 利于程序解耦合,防止改一而全改的情况出现。
- 利于程序的后期扩展。
- 利于程序的后期维护。
- 定义接口,定义方法。
- SQL映射文件
namespace
是接口的全名。- SQL映射文件的方法
id
为接口的方法名。
public void testCRUD2() {
SqlSession session = factory.openSession();
// 1.通过getMapper()方法获取映射的接口类型对象。
TeacherDao mapper = session.getMapper(TeacherDao.class);
// 2.通过直接调用接口对象中所有定义好的方法。
int result = mapper.deleteOne(16);
session.commit();
session.close();
System.out.println("=========>"+result);
}
3.方法单参传参:
1、当参数类型为基本数据类型:
- #{内容}
可以填任何,只要取一个清晰明了的名字即可。
- 也就是填 #{01324}
,#{faf}
都可以运行。
map - #{key}
obj - #{属性}
4.方法多参传参:
1、使用下标 #{0}
、#{1}
、#{2}
性获取多餐。
2、可以使用 #{param1}
、#{param2}
形式获取多参。
3、使用map,通过 #{key}
获取
<select id="findByNameAndId" resultType="Human">
select * from human
where id=#{param2} and name=#{param1}
</select>
4、在方法定义处添加 @Param(“name”)注解 对方法参数设置别名,在映射文件直接#{别名} 即可获取参数的值
此方法推荐使用,方便理解。并且不易出错。
/**
* 使用@Param注解 进行多参数传递。
* @param name 此时应该使用#{humanName}
* @param id 此时应该使用#{humanId}
* @return
*/
Human findByNameAndId(@Param("huName")String name,@Param("huId")Integer id);
<select id="findByNameAndId" resultType="Human">
select * from human
where name=#{huName} and id=#{huId}
</select>
5.mybatis的模糊查询
其实本质上和我们写SQL语法的规则是一致的,这里推荐使用concat(str 1,str 2,str 3)的SQL函数进行动态拼接。
<select id="findListByName" resultType="Human" >
select * from human
where name like concat('%',#{name},'%');
</select>
二、Mybatis映射文件
1、什么是关系映射?为什么叫对象关系映射?
ORM对象关系映射(Object Relational Mapping)
Teachar(实体类) ===> teacher(表/关系)
因为我们用的数据库为关系型数据库,一个表就是一个关系。我们说的高大上一点就是说对象关系映射,反之可以理解为对象表关系;而将实体类转化为表关系的过程 就叫做对象关系映射。
2、简单的结果集映射
适用场景:当实体类的属性和类名不一致时;或者直接配置一个resultMap供全局适用的结果Map。
resultType
和resultMap
不能同时出现。- 如果类名和数据库列名相同则自动映射。
<!-- 映射结果集 -->
<resultMap autoMapping="false" type="Human" id="humanMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<select id="findListByName" resultMap="humanMap">
select * from human
where name like concat('%',#{name},'%');
</select>
3、如何定义多对一情况的实体类。
1、什么是多对一?
简单来说所有的同一个阶段的班级对应着一个年级,多个学生同时拥有一个老师。
2、如何配置多对一?
在多的那方的实体类,添加一的对象引用。比如:每个学生都有一位共同的老师。
3、对应实体/数据库的关系映射
数据库表中的外键字段,在Java实体类中会被定义成实体对象引用;反之,多的一方在一的一方定义为集合。
class Student{
private Integer stuId;
private String stuName;
private Integer stuAge;
private String stuSex;
private Date stuBirth;
// 外键字段在实体类中,会定义为引用对象。
private Grade grade;
}
class Grade{
private Integer gradeId;
private String gradeName;
// 一对多的一方使用set、或者list集合。
List<Student> students;
}
4、多对一的映射方式
1、使用 引用对象.属性名 方式进行手动映射。
实体类中含有一个引用对象的时候,我们不能同时为本实体类进行映射的同时,为本实体类中的引用对象进行自动映射。我们需要手动指定。
<!-- 方式1:使用对象.属性的方式进行自动映射。 -->
<resultMap type="Student" autoMapping="true" id="StudentMap">
<!-- 其实属于Student表的字段可以无需填写,autoMapping为true可以自动进行映射 -->
<id property="stuId" column="stuId"/>
<result property="stuName" column="stuName"/>
<result property="stuAge" column="stuAge"/>
<result property="stuSex" column="stuSex"/>
<result property="stuBirth" column="stuBirth"/>
<!-- 外部引用的对象需要手动进行映射 -->
<result property="grade.gradeId" column="gradeId"/>
<result property="grade.gradeName" column="gradeName"/>
</resultMap>
2、使用 association 标签进行手动映射。
关键属性:property、javaType :对象的类型、 resultMap:引用外部结果集 ;
<resultMap type="Student" autoMapping="true" id="StudentMap2">
<!-- 其实属于Student表的字段可以无需填写,autoMapping为true可以自动进行映射 -->
<id property="stuId" column="stuId"/>
<!-- autoMapping默认为true,可以不指定。property属性和javaType属性必须制定。-->
<association property="grade" javaType="Grade" autoMapping="true"/>
<!-- 手动进行映射
<association property="grade" javaType="Grade">
<id property="gradeId" column="gradeId"/>
<result property="gradeName" column="gradeName"/>
</association> -->
</resultMap>
4.2、ResultMap的extends的使用。
1.项目实际开发中可以在每张SQL文件中定义一个基本的 Base_resultMap
作为父级;
2.Base_resultMap
只对当前的实体类自身属性作为映射。
3.当查询包含了复杂的关系映射时的resultMap使用extends
属性,继承 Base_resultMap
`。
4.同时可以在复杂的对象映射中使用resultMap属性进行引用,其他实体类的 Base_resultMap
。
5.好处:代码复用,减少重复的效果。也提升了后期可维护度,并且简单清晰明了易懂。
<!-- 每个SQL映射文件中设置一个基本的结果映射集 -->
<resultMap type="Student" id="stuMapBase">
<id property="stuId" column="stuId"/>
<result property="stuName" column="stuName"/>
<result property="stuAge" column="stuAge"/>
<result property="stuSex" column="stuSex"/>
<result property="stuBirth" column="stuBirth"/>
</resultMap>
<!-- 继承基本的stu的结果集,再定义一个额外的结果集。 -->
<resultMap type="Student" id="stuMapWithGrade" extends="stuMapBase">
<!-- 引用其他基本类型或者本类型的 Base_resultMap -->
<association property="grade" resultMap="com.mapper.GradeMapper.MapBase"/>
</resultMap>
4.1、关于引用外部ResultMap:
引用其他SQL映射文件的 ResultMap
需要使用 namespace+resultMap的id 的方式进行,而同命名空间则不需要。
<!-- ======================mapper.grade.gradeMapper中===================== -->
<resultMap type="Grade" id="gradeMapBase">
<id property="gradeId" column="gradeId" />
<result property="gradeName" column="gradeName"/>
</resultMap>
<!-- ======================mapper.student.stuMapper中===================== -->
<resultMap type="Student" autoMapping="true" id="StudentMap2">
<!-- 引用外部SQL文件的reusultMap -->
<association property="grade" resultMap="mapper.grade.GradeMapper.BaseMap"/>
</resultMap>
5.一对多映射方式-进行双向关联
1、使用collection标签进行List集合关系的映射。
关键属性:property、ofType:集合属于的类型 、 resultMap:引用外部结果集 ;
<resultMap type="Grade" id="gradeMapBase">
<id property="gradeId" column="gradeId" />
<result property="gradeName" column="gradeName"/>
</resultMap>
<resultMap type="Grade" extends="gradeMapBase" id="MapWithStus">
<!-- 方式1:开启自动映射,字段名和db列名要求一致 -->
<collection property="students" ofType="Student" autoMapping="true"/>
<!-- 方式2:引用学生表定义好的 Base_resultMap -->
<collection property="stus" ofType="Stu" resultMap="mapper.stu.stuMap"/>
<!-- 方式3:字段类型和数据库类型不一致,又不想定义baseresultMap时使用。 -->
<collection property="stus" ofTyep="Stu">
<id property="stuId" column="stu_id"/>
...
<result property="stuName" column="stu_name"/>
...
</collection>
</resultMap>
三、总结和自动映射级别
1、小结
1、高级结果映射
a、映射普通属性 :<id>、<result>
a、映射单个实体对象:<association>
b、映射实体集合对象:<collection>
2、resultMap的继承(extends)
3、通过继承,可以将resultMap切分父级和子级,提高效率。
4、association、collection 中可以引用别的resultMap,使得代码重用。
2、自动映射级别
当实体类属性名和数据库字段名一致时,可以无需手动映射。
原因:Mybatis.xml核心配置文件
<settings>
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
**autoMappingBehavior:**表示开启自动映射,以下有三个值。
NONE
- 不进行自动映射。PARTIAL
- 局部自动映射。- 当resultMap出现association、collection时,将不自动映射autoMapping = “false”。
- 解决方法1:设置全局为FULL。
- 解决方法2:设置SQL文件标签内的autoMapping = “true”
FULL
- 完全自动映射(物极必反,影响性能不推荐)
所有的自动映射成立的条件: 必须 属性名和列名相同的情况下。
三、Log4j复习
1、Log4j简介:
由 apache 推出的开源免费日志处理的类库。
2、为什么需要日志:
在项目中编写System.out.println();输出到控制台,当项目发布到tomcat 后,没有控制台(在命令行界面能看见.),不容易观察一些输出结果。
log4j 作用,不仅能把内容输出到控制台,还能把内容输出到文件中。便于观察结果。
3、使用步骤:
- 导入log4j的jar包。
- 在src路径下创建log4j.properties(名称不可以改变)
4、Log4j输出级别:
fatel(致命错误)> error > warn > info > debug
5、在类中使用Log4j
private static Logger log = Logger.getLogger(所在类名.class);
//输出级别
log.debug();
log.info();
log.warn();
log.error();
6、常用输出表达式
%C – 包名+类名
%d{YYYY-MM-dd HH:mm:ss} 时间
%L – 行号
%m – 信息
%n – 换行