Mybatis第二天

一、可以优化的几个地方:

1、将数据库连接的设置放在一个配置文件中

  db.properties

jdbc.driverName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root

  在mybatis配置文件中引用db.properties

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--    读取数据库配置文件-->
    <properties resource="db.properties"></properties>


    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverName}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
  
</configuration>
View Code

2、给实体类起别名,简化映射文件中对实体类引用的写法

  别名在mybatis配置文件中设置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--    给实体类起别名-->
    <typeAliases>
        <!--    1、单独给一个实体类起别名,该例的别名就是“s”-->
        <!--        <typeAlias type="com.fy.bbb.entity.SalGrade" alias="s"></typeAlias>-->
        <!--    2、给整个包起别名,类的别名就是类名    -->
       <package name="com.fy.bbb.entity"/>
    </typeAliases>


    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverName}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/SalGradeMapper.xml"></mapper>
    </mappers>
</configuration>
View Code

  配置文件中对别名的使用

<?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">
<mapper namespace="com.fy.bbb.dao.SalGradeDao">

       <select id="getAll" resultType="s">
           select * from salgrade
       </select>

</mapper>
View Code

 3、解决实体类中的字段和数据表字段不对应的问题

  ①、给数据库查询语句起别名,别名和实体类字段名相同

<?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">
<mapper namespace="com.fy.bbb.dao.SalGradeDao">
    <!--    解决java实体类字段和数据库字段不相同的问题-->
    <!--    1、给sql语句中的字段起别名-->
    <select id="getAll" resultType="com.fy.bbb.entity.SalGrade">
          select grade as g from salgrade
       </select>
</mapper>
View Code

  ②、在配置文件中使用resultMap,将数据库表字段和实体类属性一 一对应。resultMap还是连表查询必须要用的

<?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">
<mapper namespace="com.fy.bbb.dao.SalGradeDao">
    <!--    解决java实体类字段和数据库字段不相同的问题-->

    <!--    2、使用resultMap-->
    <resultMap id="baseMap" type="com.fy.bbb.entity.SalGrade">
        <!--       id标签中映射主键列   column中写数据库字段    property中写java实体类的属性-->
        <id column="id" property="id"></id>
        <!--       result标签映射其他列-->
        <result column="grade" property="grade"></result>
        <result column="losal" property="losal"></result>
        <result column="hisal" property="hisal"></result>
    </resultMap>

    <select id="getAll" resultType="com.fy.bbb.entity.SalGrade">
           select * from salgrade
       </select>
</mapper>
View Code

4、加入日志

 步骤:

  ①、导入jar包

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>
View Code

  ②、写配置文件  log4j.properties

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
View Code

二、连表查询

  注:使用mybatis查询时,我们要指定resultMap或者resultType。连表查询时就不是一个单一的实体类就能接收数据了,所以要在实体类之间相互引用

  准备表数据:class表和teacher表

CREATE TABLE teacher(
t_id INT PRIMARY KEY AUTO_INCREMENT,
t_name VARCHAR(20)
);
CREATE TABLE class(
c_id INT PRIMARY KEY AUTO_INCREMENT,
c_name VARCHAR(20),
teacher_id INT
);
ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id)
REFERENCES teacher(t_id);
INSERT INTO teacher(t_name) VALUES('LS1');
INSERT INTO teacher(t_name) VALUES('LS2');
INSERT INTO class(c_name, teacher_id) VALUES('bj_a', 1);
INSERT INTO class(c_name, teacher_id) VALUES('bj_b', 2);
View Code

  ①、多对一:多个职员对应一个级别,此时就要将级别表实体类引入到职员表的实体类中

  实体类:

    class:班级实体类 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Clazz {  //
    private int cid;
    private String cname;
    private Teacher teacher;//该班级对应的老师信息
}
View Code

    teacher:老师实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private int tid;
    private String tname;
}
View Code

  映射文件:classMapper.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 namespace="com.ykq.dao.ClazzDao">

    <!--联表查询得到的结果-->
    <resultMap id="ClazzMap" type="com.ykq.entity.Clazz">
           <id column="c_id" property="cid"/>
           <result column="c_name" property="cname"/>
           <!--association多对一的映射
                     javaType:表示属性名对应的java实体类类型
           -->
           <association property="teacher" javaType="com.ykq.entity.Teacher">
                 <!--该属性的名称与字段的对应关系-->
               <id column="t_id" property="tid"/>
               <result column="t_name" property="tname"/>
           </association>
    </resultMap>

    <!--只要使用联表查询 必须使用resultMap-->
    <select id="findClassByid" resultMap="ClazzMap">
        select * from class c,teacher t where c.teacher_id=t.t_id
         and c.c_id=#{cid}
    </select>

</mapper>
View Code

  第二种写法,将sql语句分开写,改动仅是映射文件。

  先查询班级,再查班级中对应的老师,两次查询

<?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 namespace="com.ykq.dao.ClazzDao">

    <!--两次查询得到结果-->

    <resultMap id="ClazzMap" type="com.ykq.entity.Clazz">
        <id column="c_id" property="cid"/>
        <result column="c_name" property="cname"/>

        <!--column:把第一次查询的某一列作为第二次查询的值,自动赋值
             select:指定第二次要执行的sql
        -->
        <association property="teacher" javaType="com.ykq.entity.Teacher" column="teacher_id" select="findTeacherById">
            <id column="t_id" property="tid"/>
            <result column="t_name" property="tname"/>
        </association>
    </resultMap>

    <select id="findClassByid" resultMap="ClazzMap">
          select * from class where c_id=#{cid}
    </select>

    <select id="findTeacherById" resultType="com.ykq.entity.Teacher">
          select t_id tid,t_name tname from teacher where t_id=#{tid}
    </select>

</mapper>
View Code

  ②、一对多:一个班级对应多个学生,应为是多个学生,所以要把学生实体类引用班级实体类中时要用集合的方式

  创建学生表:  

CREATE TABLE student(
s_id INT PRIMARY KEY AUTO_INCREMENT,
s_name VARCHAR(20),
class_id INT
);
INSERT INTO student(s_name, class_id) VALUES('xs_A', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_B', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_C', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_D', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_E', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_F', 2);
View Code

  Student:学生实体类

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {
    private int sId;
    private String sname;
}
View Code

  class:班级实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Clazz {  //
    private int cid;
    private String cname;
    private Teacher teacher;//该班级对应的老师信息

    //表示该班级下所有的学生信息
    private List<Student> students;
}
View Code

   教师表不动。

  映射文件:classMapper.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 namespace="com.ykq.dao.ClazzDao">



    <!--联表查询得到的结果-->
    <resultMap id="ClazzMap" type="com.ykq.entity.Clazz">
           <id column="c_id" property="cid"/>
           <result column="c_name" property="cname"/>
           <!--association多对一的映射
                     javaType:表示属性名对应的java实体类类型
           -->
           <association property="teacher" javaType="com.ykq.entity.Teacher">
                 <!--该属性的名称与字段的对应关系-->
               <id column="t_id" property="tid"/>
               <result column="t_name" property="tname"/>
           </association>

            <!--ofType:表示集合的泛型-->
           <!--collection:一对多的配置使用collection-->
           <collection property="students" ofType="com.ykq.entity.Student">
                <id column="s_id" property="sId"/>
               <result column="s_name" property="sname"/>
           </collection>

    </resultMap>
    <!--只要使用联表查询 必须使用resultMap-->
    <select id="findClassByid" resultMap="ClazzMap">
        select * from class c,teacher t,student s where c.teacher_id=t.t_id
         and c.c_id=s.class_id
         and c.c_id=1  and c.c_id &lt;=1
    </select>

</mapper>        
View Code

三、xml碰见特殊字符的处理

  例:再sql语句中使用小于“<”就会出问题

  解决方法:

  ①可以使用转义字符

    

  ②、使用CDATA

  

 <select id="findClassBetweenIds" resultMap="ClazzMap">
        <![CDATA[select * from class where c_id >=#{minId}  and c_id <=#{maxId}]]>
 </select>

 

posted @ 2021-03-22 13:57  橙汁one  阅读(36)  评论(0编辑  收藏  举报