Mybatis整合Log4j、延迟加载
日志:Log4j
a.Log4j :Log4j.jar
b.开启日志
/MyBatisProject3/src/conf.xml
<settings> <!--开启日志,并指定使用的具体日志 --> <setting name="LogImpl" value="LOG4J"/> </settings>
如果不指定,Mybatis就会根据以下顺序寻找日志
SLF4J -> Apache Commons Logging -> Log4j 2 -> Log4j ->JDK logging
c.编写配置日志输出文件
log4j.properties
log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志级别:DEBUG<INFO<WARN<ERROR
如果设置为info,则只显示info及以上的级别的信息
建议:在开发时设置debug,在设置运行时设置为info或以上。
可以通过日志信息,详细的阅读mybatis执行情况(观察mybatis实际执行sql语句以及sql中的参数和返回结果)
延迟加载(懒加载):
一对一、一对多、多对一,多对多
一对多:班级-学生
如果不采用延迟加载(立即加载),查询时会将一和多都查询,班级、班级中的所有学生
如果想要暂时只查询 一的一方,而多的一方先不查询,而是在需要的时候再去查询-->延迟加载
一对一:学生、学生证
mybatis中使用延迟加载,需要先配置:
/MyBatisProject3/src/conf.xml
<settings> <!--开启延迟加载 --> <setting name="LazyLoadingEnabled" value="true"/> <!--关闭立即加载 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
/MyBatisProject3/src/org/myy/mapper/studentMapper.xml
<!--利用resultMap实现一对一 ,延迟加载 --> <select id="queryStudentByNoWithOOLazyLoad" parameterType="int" resultMap="student_card_lazyload_map"> <!--先查学生 --> select * from student1 </select> <resultMap type="student" id="student_card_lazyload_map"> <id property="stuNo" column="stuNo"/> <result property="stuName" column="stuName"/> <result property="stuAge" column="stuAge"/> <!--一对一时,对象成员使用association映射 ; javaType指定该属性的类型 此次采用延迟加载:在查询学生时,并不计师加载学生证信息 --> <!--学生证,通过select在需要的时候再查学生证 --> <association property="card" javaType="StudentCard" select="org.myy.mapper.StudentCardMapper.queryCardById" column="cardid" > <!-- <id property="cardId" column="cardId"/> <result property="cardInfo" column="cardInfo"/> --> </association> </resultMap>
/MyBatisProject3/src/org/myy/mapper/studentCardMapper.xml
<!--查询学生证信息 --> <select id="queryCardById" parameterType="int" resultType="studentCard"> <!--查询对应的学生证 --> select * from studentcard where cardid=#{cardId} </select> <!--根据cardid查询学生证的sql:org.myy.mapper.StudentCardMapper.queryCardById -->
如果增加了mapper.xml,一定要修改配置文件(将新增的mapper.xml加载进去)
/MyBatisProject3/src/conf.xml
<mapper resource="org/myy/mapper/studentCardMapper.xml"/>
/MyBatisProject3/src/org/myy/mapper/StudentMapper.java
List<Student> queryStudentByNoWithOOLazyLoad();
/MyBatisProject3/src/org/myy/test/Test.java
// Connection - SqlSession操作Mybatis // conf.xml->reader Reader reader = Resources.getResourceAsReader("conf.xml"); // reader->sqlSession // 可以通过build的第二参数 指定数据库环境 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development"); SqlSession session = sessionFactory.openSession(); StudentMapper studentMapper = session.getMapper(StudentMapper.class); //学生 List<Student> students = studentMapper.queryStudentByNoWithOOLazyLoad(); for(Student student:students) { System.out.println(student.getStuNo()+","+student.getStuName()+","+student.getStuAge()); //获取学生证 StudentCard card=student.getCard(); System.out.println(card.getCardId()+","+card.getCardInfo()); } session.close();
通过debug可以发现,如果程序只需要学生,则只向数据库发送了查询学生的SQL;
当我们后续需要用到学生整的时候,载第二次发送查询学生证的SQL;
一对多:和一对一的延迟配置方法相同
延迟加载步骤:先查班级,按需查询学生
1.开启延迟加载conf.xml配置setting
2.配置mapper.xml
写2个mapper
班级mapper.xml
/MyBatisProject3/src/org/myy/mapper/studentClassMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace:该mapper.xml映射文件的唯一标识 --> <mapper namespace="org.myy.mapper.StudentClassMapper"><!--映射文件的路径 --> <!--一对多带延迟加载 --> <select id="queryClassAndStudentsLazyLoad" parameterType="int" resultMap="class_student_lazyload_map"> <!--[1].先查询班级 --> select c.* from studentclass c </select> <!--类和表的对应关系 --> <resultMap type="studentclass" id="class_student_lazyload_map"> <!--因为type的主类是班级,因此先配置班级的信息 --> <id property="classId" column="classId"/> <result property="className" column="className"/> <!--配置成员属性,一对多;属性类型:javaType,属性的元素类型odType --> <!--[2].再查班级对应的学生 --> <collection property="students" ofType="student" select="org.myy.mapper.StudentMapper.queryStudentByClassId" column="classid"> <!-- <id property="stuNo" column="stuNo"/> <result property="stuName" column="stuName"/> <result property="stuAge" column="stuAge"/> --> </collection> </resultMap> </mapper>
即查询学生的sql是通过select属性指定,并且通过column指定外键
学生mapper.xml
/MyBatisProject3/src/org/myy/mapper/studentMapper.xml
<!--一对多,延迟加载需要的;查询班级中所有的学生 -->
<select id="queryStudentByClassId" parameterType="int" resultType="student">
select * from student1 where classId=#{classId}
</select>
/MyBatisProject3/src/org/myy/mapper/StudentClassMapper.java
package org.myy.mapper; import java.util.List; import org.myy.entity.StudentClass; //操作Mybatis的接口 public interface StudentClassMapper { /* 1.方法名和mapper.xml文件中的标签的id值相同 2.方法的输入参数和mapper.xml文件中的标签的parameterType类型一致 3.方法的返回值和mapper.xml文件中标签的resultType类型一致 */ //public abstract Student1 queryStudentByStuno(int stuno); //查询全部班级 List<StudentClass> queryClassAndStudentsLazyLoad(); }
/MyBatisProject3/src/org/myy/test/Test.java
// Connection - SqlSession操作Mybatis // conf.xml->reader Reader reader = Resources.getResourceAsReader("conf.xml"); // reader->sqlSession // 可以通过build的第二参数 指定数据库环境 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development"); SqlSession session = sessionFactory.openSession(); StudentClassMapper StudentClassMapper = session.getMapper(StudentClassMapper.class); List<StudentClass> studentClasses = StudentClassMapper.queryClassAndStudentsLazyLoad(); //班级信息 for(StudentClass studentClass:studentClasses) { System.out.println(studentClass.getClassId()+","+studentClass.getClassName()); List<Student> students=studentClass.getStudents(); for(Student student:students) { System.out.println(student.getStuNo()+","+student.getStuName()+","+student.getStuAge()); } System.out.println("------------------------------"); }