Mybatis02

马果老师整理

 

 

在实际应用mybatis中的过程中,主要是采用代理的方式配置mybatis:

代理配置mybatis的特点:

  1. Dao层主要是编写接口,不需要编写实现类
  2. Dao接口的名称必须要与Mapper映射文件的名称一样,只是后缀名不同
  3. Mapper.xml文件的namespace必须是:Mapper接口的全路径 

自动生成实体类和dao包接口和映射文件

用插件生成:

  1. 实体类
  2. Mapper接口
  3. Mapper映射文件

准备工作:

1、在mybatis网站中,下载一个插件包(jar)

  • mybatis-generator-core-1.3.2.jar
  • mysql-connector-java-3.1.10-bin.jar

2、准备一个用于生成代码的配置文件xml

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE generatorConfiguration  
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">  
<generatorConfiguration>  
    <!-- 数据库驱动,当前文件下驱动包的名称要和location对应-->  
    <classPathEntry  location="驱动包名称"/>  
    <context id="DB2Tables"  targetRuntime="MyBatis3">  
        <commentGenerator>  
            <property name="suppressDate" value="true"/>  
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->  
            <property name="suppressAllComments" value="true"/>  
        </commentGenerator>  
        <!--数据库链接URL,用户名、密码 -->  
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mydb" userId="root" password="root">  
        </jdbcConnection>  
        <javaTypeResolver>  
            <property name="forceBigDecimals" value="false"/>  
        </javaTypeResolver>  
        <!-- 生成模型entity的包名和位置-->  
        <javaModelGenerator targetPackage="org.java.entity" targetProject="项目的路径地址\src">  
            <property name="enableSubPackages" value="true"/>  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
        <!-- 生成映射文件的包名和位置-->  
        <sqlMapGenerator targetPackage="org.java.dao" targetProject="项目的路径地址\src">  
            <property name="enableSubPackages" value="true"/>  
        </sqlMapGenerator>  
        <!-- 生成DAO的包名和位置-->  
        <javaClientGenerator type="XMLMAPPER" targetPackage="org.java.dao" targetProject="项目的路径地址\src">  
            <property name="enableSubPackages" value="true"/>  
        </javaClientGenerator>  
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->  
        <table tableName="inf" domainObjectName="Inf" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>  
</generatorConfiguration>  

3、修改xml文件中的内容 

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE generatorConfiguration  
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">  
<generatorConfiguration>  
<!-- 数据库驱动-->  
    <classPathEntry  location="mysql-connector-java-3.1.10-bin.jar"/>  
    <context id="DB2Tables"  targetRuntime="MyBatis3">  
        <commentGenerator>  
            <property name="suppressDate" value="true"/>  
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->  
            <property name="suppressAllComments" value="true"/>  
        </commentGenerator>  
        <!--数据库链接URL,用户名、密码 -->  
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mydb" userId="root" password="root">  
        </jdbcConnection>  
        <javaTypeResolver>  
            <property name="forceBigDecimals" value="false"/>  
        </javaTypeResolver>  
        <!-- 生成模型entity的包名和位置-->  
        <javaModelGenerator targetPackage="org.java.entity" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <property name="enableSubPackages" value="true"/>  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
        <!-- 生成映射文件的包名和位置-->  
        <sqlMapGenerator targetPackage="org.java.dao" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <property name="enableSubPackages" value="true"/>  
        </sqlMapGenerator>  
        <!-- 生成DAO的包名和位置-->  
        <javaClientGenerator type="XMLMAPPER" targetPackage="org.java.dao" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <property name="enableSubPackages" value="true"/>  
        </javaClientGenerator>  
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->  
        <table tableName="inf" domainObjectName="Inf" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>  
</generatorConfiguration>  

4、在cmd模式下,进入插件所在目录,执行下列命令:

  1. win+r,进入cmd
  2. 进入插件所放的目录,我的在E:\mysql
  3. 执行java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite

如果需要生成当前数据库里的所有表,则:

<!-- 要生成的所有表 tableName里面写% 去掉domainObjectName-->  
<table tableName="%" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>

自动生成Oracle数据库里的表

只需改变generatorConfig.xml里的值

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE generatorConfiguration  
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">  
<generatorConfiguration>  
<!-- 数据库驱动-->  
    <classPathEntry  location="ojdbc6.jar"/>  
    <context id="DB2Tables"  targetRuntime="MyBatis3">  
        <commentGenerator>  
            <property name="suppressDate" value="true"/>  
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->  
            <property name="suppressAllComments" value="true"/>  
        </commentGenerator>  
        <!--数据库链接URL,用户名、密码 -->  
        <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1521:XE" userId="d91" password="d91">  
        </jdbcConnection>  
        <javaTypeResolver>  
            <property name="forceBigDecimals" value="false"/>  
        </javaTypeResolver>  
        <!-- 生成模型entity的包名和位置-->  
        <javaModelGenerator targetPackage="org.java.entity" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <!-- 关闭启用子包名称-->  
            <property name="enableSubPackages" value="false"/>  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
        <!-- 生成映射文件的包名和位置-->  
        <sqlMapGenerator targetPackage="org.java.dao" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <!-- 关闭启用子包名称-->  
            <property name="enableSubPackages" value="false"/>  
        </sqlMapGenerator>  
        <!-- 生成DAO的包名和位置-->  
        <javaClientGenerator type="XMLMAPPER" targetPackage="org.java.dao" targetProject="D:\space\eclipseSpace\j54\spring_j54_9_1\src">  
            <!-- 关闭启用子包名称-->  
            <property name="enableSubPackages" value="false"/>  
        </javaClientGenerator>  
        <!-- 要生成的表 tableName为%表示生成所有表,schema表示生成d91用户下的表-->  
        <table tableName="%" schema="d91" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>  
</generatorConfiguration>  

 

数据库中的表,如果存在一定关联,通过mybatis进行映射以后,它们会产生关联关系:

1对1  ------------one to one
            人员与身份证

1对多 ------------one to many
            省份与城市

多对1 ------------many to one
            城市与省份

多对多 -----------many to many
            学生与老师

============================================================

1对多,多对1

如果数据库的两张表之间,存在主外键关系,映射以后,它们就会存在一对多以及多对一的关系 

Province类(一)
    pid
    pname

    //映射成实体类以后,一的一方,由于主外键关联,将会产生一个关联属性

    private List<City> = new ArrayList<City>();

package org.java.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

//1
public class Province implements Serializable {

    private Integer pid;
    private String pname;

    //一的一方,产生集合类型的关联属性
    private List<City> cities = new ArrayList<>();

    public Integer getPid() {
        return pid;
    }

    public void setPid(Integer pid) {
        this.pid = pid;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public List<City> getCities() {
        return cities;
    }

    public void setCities(List<City> cities) {
        this.cities = cities;
    }
}

----------------------------------------------

City类  (多)
    cid
    cname

    private Province province;----它是外键pid,它映射以后,将会变为主键表所对应的实体类

package org.java.entity;

import java.io.Serializable;

public class City implements Serializable {

    private Integer cid;
    private String cname;

    private Province province;//关联属性(由外键产生)

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public Province getProvince() {
        return province;
    }

    public void setProvince(Province province) {
        this.province = province;
    }
}

示例

CityMapper.java

package org.java.dao;

import org.java.entity.City;

public interface CityMapper {

    public City findByCid(Integer cid);
}

CityMapper.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" >
<mapper namespace="org.java.dao.CityMapper">


    <select id="findProvinceByPid" parameterType="int" resultType="province">
        select * from province where pid=#{pid}
    </select>

    <resultMap id="cityMap" type="city">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <association property="province" column="pid" select="findProvinceByPid"/>
    </resultMap>

    <select id="findByCid" parameterType="int" resultMap="cityMap">
        select cid,cname,pid from city where cid=#{cid}
    </select>

</mapper>

测试

package org.java;

import org.apache.ibatis.session.SqlSession;
import org.java.dao.CityMapper;
import org.java.entity.City;
import org.java.util.MyBatisUtil;
import org.junit.Test;

public class CityService {


    @Test
    public void findByCid(){

        SqlSession ses = MyBatisUtil.getSession();
        CityMapper mapper = ses.getMapper(CityMapper.class);
        City city = mapper.findByCid(3);
        System.out.println("城市编号:"+city.getCid());
        System.out.println("城市名称:"+city.getCname());
        System.out.println("所属省份名称:"+city.getProvince().getPname());
        ses.close();
    }
}

mybatis中 resultMap与resultType的区别:

  • resultType:自动封装返回类型,但这种方式不能加载关联属性的数据
  • resultMap: 手动封装返回类型,这种可以加载关联属性

懒加载

默认情况下:在mybatis中,如果配置了关联查询,在查询一个对象,将会自动查询与它相关的关联属性

分析:假设,有一个主贴,这一个主贴有1万个回贴 

  • 如果配置了默认加载方式,只要一查询主贴,这1万个回贴都会加载到内存中

mybatis中,有一种延迟加载机制:(懒加载) lazy

一开始查询时,只加载数据表中有字段对应的属性,关联属性一开始并不加载,关联属性什么时候用,什么时候
加载

配置延迟加载后:类中的关联属性,什么用,什么时候才会关联表

配置懒加载

在mybatis-config.xml中的properties属性下面进行配置

    <!--相关配置-->
    <settings>
        <!--启用延迟加载机制-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--不使用积极加载(什么时候使用关联属性,什么时候查询关联表)-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

使用mybatis加载关联属性的方式有两种:

方式1: 进行二次查询

  • 一般如果使用二次查询加载关联属性,都建议采用延迟加载

方式2:采用联表查询,只查询一次 

一对一,多对一的联表查询

    <resultMap id="cityMap" type="city">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <association property="province" javaType="province">
            <id property="pid" column="pid"/>
            <result property="pname" column="pname"/>
        </association>
    </resultMap>

一对多,多对多的联表查询

    <resultMap id="provinceMap" type="province">
        <id property="pid" column="pid"/>
        <result property="pname" column="pname"/>

        <!--配置关联属性-->
        <collection property="cities" ofType="city">
            <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </collection>
    </resultMap>

    <select id="findProvinceByPid" parameterType="int" resultMap="provinceMap">
        SELECT c.cid,c.cname,p.pid,p.pname FROM city c,province p WHERE c.pid=p.pid AND p.pid=#{pid}
    </select>

联表查询时:

  • 多对一,一对一的关联属性,使用:javaType
  • 一对多,多对多的关联属性,使用:ofType

----------------------------------------------------------------------------------

一对一,多对多

一对一的配置:    人员与身份证

  • 如果是一对一的关系: 在实体类中将会产生一个关联属性,类型为关联表所映射以后的实体类型 

示例:

IdCard.java

package org.java.entity;

import java.io.Serializable;

public class IdCard implements Serializable {

    private Integer cid;//编号
    private String cno;//证件号码

    //关联属性
    private Person person;

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCno() {
        return cno;
    }

    public void setCno(String cno) {
        this.cno = cno;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

Person.java

package org.java.entity;

import java.io.Serializable;

public class Person implements Serializable {

    private Integer pid;//人员编号
    private String pname;//人员名称

    //关联属性
    private IdCard idCard;

    public Integer getPid() {
        return pid;
    }

    public void setPid(Integer pid) {
        this.pid = pid;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public IdCard getIdCard() {
        return idCard;
    }

    public void setIdCard(IdCard idCard) {
        this.idCard = idCard;
    }
}

PersonMapper.java

package org.java.dao;

import org.java.entity.Person;

public interface PersonMapper {

    public Person findPerson(int pid);
}

PersonMapper.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" >
<mapper namespace="org.java.dao.PersonMapper">

    <resultMap id="personMap" type="person">
        <id property="pid" column="pid"/>
        <result property="pname" column="pname"/>
        <association property="idCard"  javaType="idCard">
            <id property="cid" column="cid"/>
            <result property="cno" column="cno"/>
        </association>
    </resultMap>

    <select id="findPerson" parameterType="int" resultMap="personMap">
        SELECT p.pid,p.pname,c.cid,c.cno  FROM person p LEFT OUTER JOIN idCard c ON(p.pid=c.cid) WHERE p.pid=#{pid}
    </select>
</mapper>

测试:

package org.java.service;

import org.apache.ibatis.session.SqlSession;
import org.java.dao.PersonMapper;
import org.java.entity.IdCard;
import org.java.entity.Person;
import org.java.util.MyBatisUtil;
import org.junit.Test;

public class PersonService {

    @Test
    public void findPerson(){
        SqlSession ses = MyBatisUtil.getSession();
        PersonMapper mapper=ses.getMapper(PersonMapper.class);
        Person person = mapper.findPerson(3);
        System.out.println("姓名:"+person.getPname());
        IdCard idCard = person.getIdCard();
        if(idCard==null){
            System.out.println("该用户暂无证件");
        }else{
            System.out.println("身份证号:"+idCard.getCno());
        }
        ses.close();
    }
}

多对多: many-to-many

  • 老师与学生, 开发人员与项目组
  • 多对多的本质:其实就是两个一对多,站在谁的角度看,自己就是一,对方就是多

测试数据:

CREATE TABLE teacher
(
	tid INT PRIMARY KEY,#老师编号,
	tname VARCHAR(20)#老师名称
)
INSERT INTO teacher VALUES(1,'张老师');
INSERT INTO teacher VALUES(2,'李老师');

CREATE TABLE stu
(
	sid INT PRIMARY KEY,#学生编号
	sname VARCHAR(20)#学生名称
)
INSERT INTO stu VALUES(1,'张三');
INSERT INTO stu VALUES(2,'李四');

##老师与学生的关系表
CREATE TABLE teacher_stu
(
	tid INT,#代表老师的编号
	sid INT #代表学生的编号
)

INSERT INTO teacher_stu VALUES(1,1);
INSERT INTO teacher_stu VALUES(1,2);

INSERT INTO teacher_stu VALUES(2,1);
INSERT INTO teacher_stu VALUES(2,2);


SELECT * FROM teacher_stu;

SELECT a.tid,a.tname,b.sid,b.sname FROM teacher a,stu b,teacher_stu c
	WHERE  a.tid = c.tid AND b.sid = c.sid AND a.tid=2;
								

Stu.java

package org.java.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Stu implements Serializable {

    private Integer sid;//学生编号
    private String sname;//学生姓名

    //关联属性
    private List<Teacher> teachers = new ArrayList<>();

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public List<Teacher> getTeachers() {
        return teachers;
    }

    public void setTeachers(List<Teacher> teachers) {
        this.teachers = teachers;
    }
}

Teacher.java

package org.java.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Teacher implements Serializable {

    private Integer tid;//老师编号
    private String tname;//老师名称

    //关联属性
    private List<Stu>  stus = new ArrayList<>();

    public Integer getTid() {
        return tid;
    }

    public void setTid(Integer tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public List<Stu> getStus() {
        return stus;
    }

    public void setStus(List<Stu> stus) {
        this.stus = stus;
    }
}

TeacherMapper.java

package org.java.dao;

import org.java.entity.Teacher;

public interface TeacherMapper {

    public Teacher findTeacherByTid(int tid);

}

TeacherMapper.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" >
<mapper namespace="org.java.dao.TeacherMapper">


    <resultMap id="teacherMap" type="teacher">
        <id property="tid" column="tid"/>
        <result property="tname" column="tname"/>
        <collection property="stus" ofType="stu">
            <id property="sid" column="sid"/>
            <result property="sname" column="sname"/>
        </collection>
    </resultMap>

    <select id="findTeacherByTid" parameterType="int" resultMap="teacherMap">
        SELECT a.tid,a.tname,b.sid,b.sname FROM teacher a,stu b,teacher_stu c
            WHERE  a.tid = c.tid AND b.sid = c.sid AND a.tid=#{tid}
    </select>
</mapper>

测试:

package org.java.service;

import org.apache.ibatis.session.SqlSession;
import org.java.dao.TeacherMapper;
import org.java.entity.Stu;
import org.java.entity.Teacher;
import org.java.util.MyBatisUtil;
import org.junit.Test;

import java.util.List;

public class TeacherService {

    @Test
    public void findTeacher(){

        SqlSession ses = MyBatisUtil.getSession();
        TeacherMapper mapper = ses.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.findTeacherByTid(2);
        System.out.println("老师名称:"+teacher.getTname());
        System.out.println("-----------------");
        List<Stu> stus = teacher.getStus();
        for(Stu s:stus){
            System.out.println(s.getSname());
        }
        ses.close();
    }
}

多对多的关联,不需要在数据表中用主外键描述,而是通过一张单独的关系表来描述,双方的关联 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值