解决Java EE 石毅4.5的课后操作题第1题

1.个人和身份证之间的一对一关联关系

查询个人及其关联的身份证信息是先通过查询个人表中的主键来获得个人信息的,然后通过表中的外键来获取证件表中的身份证号信息。

数据库中tb_idcard表和tb_person表的数据如图4.8所示

                                 图4.8 tb_idcard表和tb_person

在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人,它们之间的关系模型图,如图1所示。

图1 人与身份证的关联关系

那么使用MyBatis是怎么处理图1中的这种一对一关联关系的呢?在元素中,包含了一个子元素,MyBatis就是通过该元素来处理一对一关联关系的。

在元素中,通常可以配置以下属性:

● property:指定映射到的实体类对象属性,与表字段一一对应;

● column:指定表中对应的字段;

● javaType:指定映射到实体对象属性的类型;

● select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询;

● fetchType:指定在关联查询时是否启用延迟加载。fetchType属性有lazy和eager两个属性值,默认值为lazy(即默认关联映射延迟加载)。

元素的使用非常简单,只需要参考如下两种示例配置即可,具体如下:

<!--方式一:嵌套查询-->
<association property="card" column="card_id" 
javaType="com.itheima.po.IdCard"
             select="com.itheima.mapper.IdCardMapper.findCodeById" />
<!--方式二:嵌套结果-->
<association property="card" javaType="com.itheima.po.IdCard">
    <id property="id" column="card_id"/>
    <result property="code" column="code"/>
</association>

注意:

MyBatis在映射文件中加载关联关系对象主要通过两种方式:嵌套查询和嵌套结果。

嵌套查询是指通过执行另外一条SQL映射语句来返回预期的复杂类型;

嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。

开发人员可以使用上述任意一种方式实现对关联关系的加载。

了解了MyBatis中处理一对一关联关系的元素和方式后,接下来就以个人和身份证之间的一对一关联关系为例,进行详细讲解。

查询个人及其关联的身份证信息是先通过查询个人表中的主键来获取个人信息,然后通过表中的外键来获取证件表中的身份证号信息。

其具体事项步骤如下:

(1)创建数据表.

在mybatis数据库中分别创建名为tb_idcard和tb_persond的数据,同时预先插入两条数据。

其执行的SQL语句如下所示:

USE mybatis;
# 创建一个名称为tb_idcard的表
CREATE TABLE tb_idcard(
    id INT PRIMARY KEY AUTO_INCREMENT,
    CODE VARCHAR(18)
);
# 插入2条数据
INSERT INTO tb_idcard(CODE) VALUES('152221198711020624');
INSERT INTO tb_idcard(CODE) VALUES('152201199008150317');
# 创建一个名称为tb_person的表
CREATE TABLE tb_person(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32),
    age INT,
    sex VARCHAR(8),
    card_id INT UNIQUE,
    FOREIGN KEY(card_id) REFERENCES tb_idcard(id)
);
# 插入2条数据
INSERT INTO tb_person(name,age,sex,card_id) VALUES('Rose',29,'女',1);
INSERT INTO tb_person(name,age,sex,card_id) VALUES('tom',27,'男',2);

完成上述操作后,数据库tb_idcard和tb_person表中的数据如图2所示。

图2 tb_idcard和tb_person表

(2)在Eclipse中创建一个名为chapter09的Web项目,然后引入相关JAR包,log4j日志文件,MyBatisUtils工具类以及mybatis-config.xml核心配置文件。

项目环境搭建完成后的文件结构,如图3所示。

 
图3项目文件结构

(3)在项目的com.itheima.po包下创建持久化类IdCard和Person,编辑后的代码,如文件1和文件2所示。

文件1 IdCard.java

package com.itheima.po;
/**
* 证件持久化类
* /
public class IdCard {
    private Integer id;
    private String code;
    private Integer getId();
        return id;
    }
    public void setId(Integer id){
        this.id = id;
    }
    public String getCode(){
        return code;
    }
    public void setCode(String code){
        this.code = code
    }
    @Override
    public String toString(){
        return "IdCard [id=" + id + ",code=" + code + "]";
    }
} 

文件2 Person.java

package com.itheima.po;
/**
* 个人持久化类
*/
public class Person {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    private IdCard card;
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public IdCard getCard() {
        return card;
    }

    public void setCard(IdCard card) {
        this.card = card;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", card=" + card +
                '}';
    }
}

在上述两个文件中,分别定义了各自的属性以及对应的getter/setter方法,同时为了方便查看输出结果还重写了toString()方法。

(4)在com.itheima.mapper包中,创建证件映射文件IdCardMapper.xml和个人映射文件PersonMapper.xml,并在两个映射文件中编写一对一关联映射查询的配置信息,如文件3和文件4所示。

文件3 IdCardMapper.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="com.itheima.mapper.IdCardMapper">
    <!--根据id查询证件信息-->
    <select id="findCodeById" parameterType="Integer" resultType="IdCard">
        SELECT * from tb_idcard where id=#{id}
    </select>
</mapper>

文件4 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="com.itheima.mapper.PersonMapper">
    <!--嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
    <select id="findPersonById" parameterType="Integer" resultMap="IdCardWithPersonResult">
        SELECT * FROM tb_person WHERE id=#{id}
    </select>
    <resultMap type="Person" id="IdCardWithPersonResult">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <!--一对一:association使用select属性引入另外一条SQL语句-->
        <association property="card" column="card_id" javaType="IdCard" select="com.itheima.mapper.IdCardMapper.findCodeById"/>
    </resultMap>
</mapper>

在上述两个映射文件中,使用了MyBatis中的嵌套查询方式进行了个人及其关联的证件信息查询,因为返回的个人对象中除了基本属性外还有一个关联的card属性,所以需要手动编写结果映射。

从映射文件PersonMapper.xml中可以看出,嵌套查询的方法是先执行一个简单的SQL语言,然后在进行结果映射时,将关联对象在元素中使用select属性执行另一条SQL语句(即IdCardMapper.xml中的SQL)。

(5)在核心配置文件mybatis-config.xml中,引入Mapper映射文件并定义别名,如文件5所示。

文件5 mybatis-config.xml

<?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"/>
        <!--使用扫描包的形式定义别名-->
        <typeAliases>
            <package name="com.itheima.po"/>
        <typeAliases>
        <!--配置环境,默认的环境id为mysql-->
        <environments default=mysql">
            <!--配置id为mysql的数据库环境-->
            <environment id="mysql">
                <!--使用JDBC的事务管理-->
                <transactionManager type="JDBC"/>
                <!--数据库连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver} />
                    <property name="url" value="${jdbc.url}" />
                    <property name="username" value="${jdbc.username}" />
                    <property name="password value="${jdbc.password}" />
                </dataSource>
            </environment>
        </environments>
        <!--配置Mapper的位置-->
        <mappers>
            <mapper resource="com/itheima/mapper/IdCardMapper.xml" />
            <mapper resource="com/itheima/mapper/PersonMapper.xml" />
        </mapper>
    </configuration>

在上述核心配置文件中,首先引入了数据库连接的配置文件,然后使用使用扫描包的形式自定义别名,接下来进行环境的配置,最后配置Mapper映射文件的位置信息。

(6)在com.itheima.test包中,创建测试类MybatisAssociatedTest,并在类中编写测试方法findPersonByIdTest(),如文件6所示。

文件6MybatisAssociatedTest.java

package com.itheima.test

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.itheima.po.Person;
import com.itheima.utils.MybatisUtils;
/**
* Mybatis关联查询映射测试类
*/
public class MybatisAssociatedTest{
    /**
    *嵌套查询
    */
    @Test
    public void findPersonByIdTest() {
        //1、通过工具类生成SqlSession对象
        SqlSession session = MybatisUtils.getSession();
        //2、使用MyBatis嵌套查询的方式查询id为1的人的信息
        Person person = session.selectOne("com.itheima.mapper." + "PersonMapper.findPersonById",1);
        // 3.输出查询结果信息
        System.out.println(person);
        // 4.关闭SqlSession
        session.close();
    }
}

在文件6的findPersonByIdTest()方法中,首先通过MybatisUtils工具类获取了SqlSession对象,然后通过SqlSession对象的selectOne()方法获取了个人信息。

为了查看结果,这里使用了输出语句输出查询结果信息。

最后程序执行完毕时,关闭了SqlSession.

使用了JUnit4执行findPersonByIdTest()方法后,控制台的输出结果如图4所示。

图4 运行结果

从图4可以看出,使用MyBatis嵌套查询的方式查询出了个人及其关联的身份证 信息,这就是MyBatis中的一对一关联查询。

虽然使用嵌套查询的方式比较简单,但是从图4中可以看出,MyBatis嵌套查询的方式要执行多条SQL语句,这对大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大的消耗数据库性能并且会降低查询效率。

这并不是开发人员所期望的。

为此,我们可以使用MyBatis提供的嵌套结果方式,来进行关联查询。

在PersonMapper.xml中,使用MyBatis嵌套结果的方式进行个人及其关联的证件信息查询,所添加的代码如下所示:

<!--嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
<select id="findPersonBy2" parameterType="Integer" resultMap="IdCardWithPersonResoult2">
    SELECT p.*,idcard.code
    from tb_person p,tb_idcard idcard
    where p.card_id=idcard.id
    and p.id=#{id}
</select>
<resultMap type="Person" id="IdCardWithPersonResoult2">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <result property="sex" column="sex" />
    <association property="card" javaType=IdCard">
        <id property="id" column="card_id" />
        <result property="code" column="code" />
    </association>
</resultMap>

从上述代码中可以看出,MyBati是嵌套结果的方式只编写了一条复杂的多表关联的SQL语句,并且元素中继续使用相关子元素进行数据库表字段和实体类属性的一一映射。

在测试类MybatisAssociatedTest中,编写测试方法findPersonByIdTest2(),其代码如下

图5,运行结果

从图5可以看出,使用MyBatis嵌套结果的方式只执行了一条SQL语句,并且同样查询出了个人及其关联的身份证的信息。

MyBatis延迟加载的配置:

在使用MyBatis嵌套查询方式进行MyBatis关联查询映射时,使用MyBatis的延迟加载在一定程度上可以降低运行消耗并提高查询效率。

MyBatis默认没有开启延迟加载,需要在核心配置文件mybatis-config.xml中的元素内进行配置 ,具体配置方法如下:

<settings>
    <!--打开延迟加载的开关-->
    <setting name="lazyLoadingEnabled" value="true" />
    <!--将积极加载改为消息加载,即按需加载-->
    <setting name="agreesiveLazyLoading" value="false" />
</settings>

在映射文件中,MyBatis关联映射的元素和元素中都已默认配置了延迟加载属性,即默认属性fetchType="lazy"(属性fetchType="eager"表示立即加载),所以在配置文件中开启延迟加载后,无需在映射文件中再做配置。

### 回答1: 石毅是一位Java EE框架开发者,他的代码示例非常有价值。下面我将用300字回答有关石毅代码示例的问石毅的代码示例涵盖了Java EE框架的各个方面,包括Web开发、数据库访问、事务管理和安全性等。他的代码示例非常简洁而且易于理解,让人们能够很快上手。 首先,他展示了如何使用Java EE框架进行Web开发。他使用了Servlet和JSP来创建动态网页,并且演示了如何获取用户输入、处理请求和生成响应。他还展示了使用标准标签库(JSTL)和EL表达式来简化JSP页面的开发过程。 其次,石毅还展示了如何使用Java EE框架进行数据库访问。他使用了JDBC和连接池技术来连接和操作数据库,并且演示了如何执行查询、更新和事务处理。他的代码示例还包括了如何使用ORM(对象-关系映射)框架来简化数据库操作。 此外,石毅还对Java EE框架的事务管理功能进行了示例。他展示了如何使用注解和XML配置来管理事务,包括声明式和编程式事务的使用方式。他的代码示例还演示了如何处理事务的并发和回滚操作。 最后,石毅的代码示例还包括了Java EE框架的安全性方面的内容。他展示了如何使用容器(如Tomcat)的安全机制来保护Web应用,并且演示了如何使用基于角色的访问控制(RBAC)和表单验证来控制用户的访问权限。 总的来说,石毅的代码示例涵盖了Java EE框架的重要组成部分,并且通过简洁而实用的代码展示了如何使用这些功能来开发高质量的Web应用。对于正在学习和使用Java EE框架的开发者来说,这些代码示例无疑是非常宝贵的学习资源。 ### 回答2: 石毅代码示例是指作者石毅编写的一些JavaEE框架的示例代码。石毅是一个经验丰富的程序员,他根据自己多年的开发经验,总结归纳出一套高效、易用的JavaEE框架。 这些示例代码涵盖了JavaEE框架的多个方面,包括Web开发、ORM(对象关系映射)、事务管理、并发处理、安全性等。石毅代码示例可以帮助开发人员更好地理解和应用JavaEE框架,提高开发效率和质量。 以Web开发为例,石毅代码示例提供了一套简洁而强大的Web框架,可以快速构建JavaEE应用程序。示例代码包括处理请求和响应、路由分发、会话管理、表单验证和文件上传等功能。开发人员可以根据示例代码来学习和使用这个Web框架,从而快速搭建自己的Web应用。 另外,石毅的代码示例还包括了ORM框架的应用,这可以帮助开发人员简化数据库操作和对象关系映射的工作。示例代码展示了如何定义实体类、进行增删改查操作、使用查询语言和配置文件等。开发人员可以根据示例代码学习和使用ORM框架,提高数据库操作的效率。 总的来说,石毅代码示例是一份宝贵的学习资料,可以帮助开发人员更好地掌握JavaEE框架的开发技巧和最佳实践。无论是初学者还是有经验的开发人员,都可以从中受益,提升自己的技术水平。 ### 回答3: 石毅代码示例是一个基于JavaEE框架的示例代码,它展示了一些常见的JavaEE开发中的功能和用法。 首先,石毅代码示例包含了使用Servlet的示例。Servlet是JavaEE开发中的基本组件之一,它可以处理HTTP请求和响应。示例中展示了如何创建一个Servlet,并实现doGet和doPost方法来处理GET和POST请求。 其次,示例中也包含了使用JSP的示例。JSP是JavaEE开发中的模板引擎,可以将Java代码嵌入到HTML页面中。示例展示了如何创建一个简单的JSP页面,并使用标签库来显示动态数据。 此外,示例中还涵盖了使用JDBC的示例。JDBC是JavaEE开发中用于与数据库交互的API。示例展示了如何连接到数据库、执行SQL查询和更新操作,并处理结果集。 另外,示例中还包含了使用Hibernate的示例。Hibernate是JavaEE开发中的ORM框架,可以将Java对象映射到数据库表中。示例展示了如何定义实体类、配置Hibernate并执行基本的增删改查操作。 最后,石毅代码示例还包含了使用Spring框架的示例。Spring是一个开源的JavaEE开发框架,可以简化JavaEE开发的配置和管理。示例展示了如何使用Spring框架来管理依赖注入、事务管理等功能。 总之,石毅代码示例是一个全面展示了JavaEE开发中常见功能和用法的示例代码,对于想要学习或了解JavaEE开发的人来说是一个很好的参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值