SSM框架学习——MyBatis关联映射

news2024/11/27 8:42:16

MyBatis关联映射

为什么要关联映射

实际开发中,对数据库操作常常会涉及多张表,所以在OOP中就涉及对象与对象的关联关系。针对多表操作,MyBatis提供关联映射。

关联关系概述

  • 一对一:A类中定义B类的属性b,B类中定义A类属性a。
  • 一对多:一个A类类型对应多个B类。
  • 多对多:在A类中定义B的集合,B中定义A的集合。

嵌套查询与嵌套结果

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

  • 嵌套查询是在查询SQL嵌套一个子查询
  • 嵌套查询会执行多条SQL语句
  • 嵌套查询SQL语句编写相对简单

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

  • 嵌套结果是一个嵌套的多表查询SQL
  • 嵌套结果只会执行一条复杂的SQL语句
  • 嵌套结果SQL语句写起来相对麻烦

对于嵌套查询有一个问题,那就是执行多条SQL语句导致性能开销很大。于是就有了MyBatis的延迟加载——fetchType。

实践

创建表

我们还是用之前的账户连接数据库,终端命令可以如下

mysql -u db_mybatis -p

输入密码敲击回车,然后切换数据库到db_mybatis

Windows用户可以用终端或者sqlyog执行下面语句

如果你没有这个数据库请回到前面的章节创建它。

USE db_mybatis;

我们要使用一个新的customer表,所以把之前项目留下的删除掉

DROP TABLE IF EXISTS customer;

重新创建它

CREATE TABLE customer(
  `id` int(32) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `jobs` varchar(50) DEFAULT NULL,
  `phone` varchar(16) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

给这张表插入两条数据方便我们接下来写代码用

INSERT  INTO customer(`id`,`username`,`jobs`,`phone`) VALUES (1,'zhangsan','teacher','11111111111'),(2,'lisi','student','11111111112');

创建一张idcard表,并设置主键(主码)为id

如果之前存在请删除

DROP TABLE IF EXISTS `idcard`;
CREATE TABLE idcard(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

同样插入两条数据(身份证号是我瞎编的,为了防止巧合不一定符合真实格式,但长度与现实一样)

INSERT  INTO idcard(`id`,`code`) VALUES(1,'37010219800X051118'),(2,'370203199X09092222');

创建persion表,并插入数据

DROP TABLE IF EXISTS person;

CREATE TABLE person(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `card_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_person` (`card_id`),
  CONSTRAINT `FK_person` FOREIGN KEY (`card_id`) REFERENCES `idcard` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO person(`id`,`name`,`age`,`card_id`) values (1,'张三',18,1),(2,'李四',18,2);

创建product表并插入数据

DROP TABLE IF EXISTS product;

CREATE TABLE product(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `price` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO product(`id`,`name`,`price`) values (1,'笔记本电脑',8888.8),(2,'华为手机',6666.6);

创建user表并插入数据

DROP TABLE IF EXISTS user;

CREATE TABLE user(
  `id` int(11) NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO user(`id`,`name`,`password`) values (1,'zhangsan','654321'),(2,'lisi','123456');

创建orders

DROP TABLE IF EXISTS orders;
CREATE TABLE orders(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `number` varchar(32) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_orders` (`user_id`),
  CONSTRAINT `FK_orders` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `orders`(`id`,`number`,`user_id`) VALUES (1,'201901',1);

创建orderitem表,还是一样,如果之前存在先删除。这个表一定放后面,否则创建外键会报错。

DROP TABLE IF EXISTS orderitem;

CREATE TABLE orderitem(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orders_id` int(11) DEFAULT NULL,
  `product_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_orderitem` (`orders_id`),
  KEY `FK_orderitem_product` (`product_id`),
  CONSTRAINT `FK_orderitem_product` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`),
  CONSTRAINT `FK_orderitem` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO orderitem(`id`,`orders_id`,`product_id`) VALUES (1,1,1),(2,1,2);

构建项目

我们新创建一个Maven项目top.cairbin.test5

pom.xml添加依赖包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>top.cairbin</groupId>
  <artifactId>test5</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>test5</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    
    <dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.33</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
		<dependency>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-core</artifactId>
			<version>1.4.0</version>
		</dependency>
    
    	<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
    
  </dependencies>
</project>

创建与src平级的resources目录,并右键->Build Path->Use as Source Folder

在里面添加一个数据库配置文件db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis
jdbc.username=db_mybatis
jdbc.password=db_mybatis

配置MyBatis,在同目录下创建mybatis-config.xml,这个文件会使用db.properties里面的配置,以${...}的方式调用,在<properties resource="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" />
	<settings>
		<!-- 延迟加载的开关 -->
		<setting name="lazyLoadingEnabled" value="false" />
		<!-- 设置积极加载(true)或按需加载(false) -->
		<setting name="aggressiveLazyLoading" value="true" />
		<setting name="mapUnderscoreToCamelCase" value="true" />
		<setting name="logImpl" value="STDOUT_LOGGING" />
	</settings>
	<typeAliases>
		<package name="top.cairbin.test5" />
	</typeAliases>
	<!--1.配置环境 ,默认的环境id为mysql -->
	<environments default="mysql">
		<!--1.2.配置id为mysql的数据库环境 -->
		<environment id="mysql">
			<!-- 使用JDBC的事务管理 -->
			<transactionManager type="JDBC" />
			<!--数据库连接池 -->
			<dataSource type="POOLED">
				<!-- 数据库驱动 -->
				<property name="driver" value="${jdbc.driver}" />
				<!-- 连接数据库的url -->
				<property name="url" value="${jdbc.url}" />
				<!-- 连接数据库的用户名 -->
				<property name="username" value="${jdbc.username}" />
				<!-- 连接数据库的密码 -->
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<!--2.配置Mapper的位置 -->
	<mappers>
		<mapper resource="top/cairbin/test5/mapper/CustomerMapper.xml" />
		<mapper resource="top/cairbin/test5/mapper/UserMapper.xml" />
		<mapper resource="top/cairbin/test5/mapper/IdCardMapper.xml" />
		<mapper resource="top/cairbin/test5/mapper/OrdersMapper.xml" />
		<mapper resource="top/cairbin/test5/mapper/PersonMapper.xml" />
		<mapper resource="top/cairbin/test5/mapper/ProductMapper.xml" />
	</mappers>
</configuration>

注意上方的<mapper>的目录,我们一会介绍。

然后添加log4j的配置文件log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.top.cairbin.test5=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

Dao层

我们先把对应的类创建了再说,到src/main/javatop.cairbin.test5创建一个子包,名称为top.cairbin.test5.dao

在我们新创建的包下面编写若干个类

首先是Person类,此时我们的IdCard还没创建,IDE提示错误很正常

package top.cairbin.test5.dao;

public class Person {
	private Integer id;
	private String name;
	private Integer age;
	private Integer cardId;
	private IdCard card;

	public void setId(Integer id) {
		this.id = id;
	}
	
	public Integer getId() {
		return this.id;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}
	
	public void setAge(Integer age) {
		this.age = age;
	}
	
	public Integer getAge() {
		return this.age;
	}
	
	public Integer getCardId() {
        return cardId;
    }

    public void setCardId(Integer cardId) {
        this.cardId = cardId;
    }
	
	public void setCard(IdCard card) {
		this.card = card;
	}
	
	public IdCard getCard() {
		return this.card;
	}	
}

接下来创建IdCard

package top.cairbin.test5.dao;

public class IdCard {
    private Integer id;
    private String code;

    public 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 == null ? null : code.trim();
    }
}

然后是Customer

package top.cairbin.test5.dao;

public class Customer {
    private Integer id;
    private String username;
    private String jobs;
    private String phone;

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username == null ? null : username.trim();
    }

    public String getJobs() {
        return jobs;
    }

    public void setJobs(String jobs) {
        this.jobs = jobs == null ? null : jobs.trim();
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone == null ? null : phone.trim();
    }
}

接着是Orders

package top.cairbin.test5.dao;

package top.cairbin.test5.dao;

import java.util.List;

public class Orders {
    private Integer id;
    private String number;
    private Integer userId;
    
    private List<Product> productList;

    public Integer getId() {
        return id;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    
    public void setProductList(List<Product> productList) {
    	this.productList = productList;
    }

    public List<Product> getProductList(){
    	return this.productList;
    }   
}

Product

package top.cairbin.test5.dao;

public class Product {
    private Integer id;
    private String name;
    private Double price;

    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 == null ? null : name.trim();
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

User

package top.cairbin.test5.dao;

import java.util.List;

public class User {
    private Integer id;
    private String name;
    private String password;

    private List<Orders> ordersList;
    
    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 == null ? null : name.trim();
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }
    
    public void setOrdersList(List<Orders> ordersList) {
    	this.ordersList = ordersList;
    }
    
    public List<Orders> getOrdersList(){
    	return this.ordersList;
    }   
}

Util层

这一层我们来放置一些工具类。创建包top.cairbin.test5.util

然后在下面创建MyBatisHelper

package top.cairbin.test5.util;

import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisHelper {
	private static SqlSessionFactory sqlSessionFactory = null;
	// 初始化SqlSessionFactory对象
	static {
		try {
			// 使用MyBatis提供的Resources类加载MyBatis的配置文件
			Reader reader = 
					Resources.getResourceAsReader("mybatis-config.xml");
			// 构建SqlSessionFactory工厂
			sqlSessionFactory = 
					new SqlSessionFactoryBuilder().build(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	// 获取SqlSession对象的静态方法
	public static SqlSession getSession() {
		return sqlSessionFactory.openSession();
	}
}

Mapper层

接下来我们再为top.cairbin.test5创建一个子包top.cairbin.test5.mapper,该层主要实现数据持久化。

与上面不一样的是,我们这里定义的是接口

首先是CustomerMapper接口

package top.cairbin.test5.mapper;

import top.cairbin.test5.dao.Customer;

public interface CustomerMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Customer record);

    int insertSelective(Customer record);

    Customer selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Customer record);

    int updateByPrimaryKey(Customer record);
}

到这里你可能会问,谁去实现它们呢,还记得mybatis-config.xml里那些<mapper>吗,它们每一个都指定resource到Mapper层,也就是说我们要在这里写XML文件让MyBatis实现这些方法。

第一个是CustomerMapper.xml,注意此处的namespace<resultMap>id,下文同理。

<?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="top.cairbin.test5.mapper.CustomerMapper">
  <resultMap id="BaseResultMap" type="top.cairbin.test5.dao.Customer">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="username" jdbcType="VARCHAR" property="username" />
    <result column="jobs" jdbcType="VARCHAR" property="jobs" />
    <result column="phone" jdbcType="VARCHAR" property="phone" />
  </resultMap>
  <sql id="Base_Column_List">
    id, username, jobs, phone
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from customer
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from customer
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.Customer">
    insert into customer (id, username, jobs, 
      phone)
    values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{jobs,jdbcType=VARCHAR}, 
      #{phone,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.Customer">
    insert into customer
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="username != null">
        username,
      </if>
      <if test="jobs != null">
        jobs,
      </if>
      <if test="phone != null">
        phone,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="username != null">
        #{username,jdbcType=VARCHAR},
      </if>
      <if test="jobs != null">
        #{jobs,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        #{phone,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.Customer">
    update customer
    <set>
      <if test="username != null">
        username = #{username,jdbcType=VARCHAR},
      </if>
      <if test="jobs != null">
        jobs = #{jobs,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        phone = #{phone,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.Customer">
    update customer
    set username = #{username,jdbcType=VARCHAR},
      jobs = #{jobs,jdbcType=VARCHAR},
      phone = #{phone,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

对了,请检查你XML中的方法的parameterType属性以及resultType对应类型的包是否正确!!!

然后是IdCardMapper接口

package top.cairbin.test5.mapper;

import top.cairbin.test5.dao.IdCard;

public interface IdCardMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(IdCard record);

    int insertSelective(IdCard record);

    IdCard selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(IdCard record);

    int updateByPrimaryKey(IdCard record);
}

同样在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="top.cairbin.test5.mapper.IdCardMapper">
  <resultMap id="BaseResultMap" type="top.cairbin.test5.dao.IdCard">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="code" jdbcType="VARCHAR" property="code" />
  </resultMap>
  <sql id="Base_Column_List">
    id, code
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from idcard
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from idcard
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.IdCard">
    insert into idcard (id, code)
    values (#{id,jdbcType=INTEGER}, #{code,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.IdCard">
    insert into idcard
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="code != null">
        code,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="code != null">
        #{code,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.IdCard">
    update idcard
    <set>
      <if test="code != null">
        code = #{code,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.IdCard">
    update idcard
    set code = #{code,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

然后是ProductMapper接口以及ProductMapper.xml

package top.cairbin.test5.mapper;
import top.cairbin.test5.dao.Product;

public interface ProductMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Product record);

    int insertSelective(Product record);

    Product selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Product record);

    int updateByPrimaryKey(Product record);
}
<?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="top.cairbin.test5.mapper.ProductMapper">
  <resultMap id="BaseResultMap" type="top.cairbin.test5.dao.Product">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="price" jdbcType="DOUBLE" property="price" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, price
  </sql>
  
  <select id="findProductByOrderId" parameterType="Integer"   resultType="Product">
		SELECT * from product where id IN(
		   SELECT product_id FROM orderitem  WHERE orders_id = #{id}
		)
	</select>

  
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from product
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from product
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.Product">
    insert into product (id, name, price
      )
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{price,jdbcType=DOUBLE}
      )
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.Product">
    insert into product
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="price != null">
        price,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="price != null">
        #{price,jdbcType=DOUBLE},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.Product">
    update product
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="price != null">
        price = #{price,jdbcType=DOUBLE},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.Product">
    update product
    set name = #{name,jdbcType=VARCHAR},
      price = #{price,jdbcType=DOUBLE}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

对于剩下来的几个Dao层类对应的Mapper需要特别注意下,因为它们的类里都包含复合类型,这也是我们这一章节真正要学习的东西——关联映射。

PersonMapper接口

package top.cairbin.test5.mapper;

import top.cairbin.test5.dao.Person;

public interface PersonMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Person record);

    int insertSelective(Person record);

    Person selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Person record);

    int updateByPrimaryKey(Person record);
}

PersonMapper.xml文件,请重点关注findPersonByIdfindPersonById2这两个地方。

<?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="top.cairbin.test5.mapper.PersonMapper">

	<resultMap id="BaseResultMap" type="top.cairbin.test5.dao.Person">
    	<id column="id" jdbcType="INTEGER" property="id" />
    	<result column="name" jdbcType="VARCHAR" property="name" />
    	<result column="age" jdbcType="INTEGER" property="age" />
    	<result column="card_id" jdbcType="INTEGER" property="cardId" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, age, card_id
  </sql>
  
  <!-- 嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
	<select id="findPersonById" parameterType="Integer" 
    resultMap="IdCardWithPersonResult">
		SELECT * from 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" />
		<!-- 一对一:association使用select属性引入另外一条SQL语句 -->
		<association property="card" column="card_id" javaType="top.cairbin.test5.dao.IdCard"
			select="top.cairbin.test5.mapper.IdCardMapper.selectByPrimaryKey" />
	</resultMap>

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

  
  
  
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from person
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from person
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.Person">
    insert into person (id, name, age, 
      card_id)
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, 
      #{cardId,jdbcType=INTEGER})
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.Person">
    insert into person
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="age != null">
        age,
      </if>
      <if test="cardId != null">
        card_id,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        #{age,jdbcType=INTEGER},
      </if>
      <if test="cardId != null">
        #{cardId,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.Person">
    update person
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        age = #{age,jdbcType=INTEGER},
      </if>
      <if test="cardId != null">
        card_id = #{cardId,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.Person">
    update person
    set name = #{name,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER},
      card_id = #{cardId,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

对于上面这么长的文件,最重要的地方是这里

<!-- 一对一:association使用select属性引入另外一条SQL语句 -->
<association property="card" column="card_id"   javaType="top.cairbin.test5.dao.IdCard"
select="top.cairbin.test5.mapper.IdCardMapper.selectByPrimaryKey" />

为了看到效果,我们在mybatis-config.xml里将延迟加载关掉。

<settings>
	<!-- 延迟加载的开关 -->
	<!-- 为了让大家看到关联关系的效果,我们在这里关闭了延迟加载 -->  
	<setting name="lazyLoadingEnabled" value="false" />  
	<setting name="aggressiveLazyLoading" value="true"/>  
</settings>

创建UserMapper接口和UserMapper.xml

package top.cairbin.test5.mapper;

import top.cairbin.test5.dao.User;

public interface UserMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(User record);

    int insertSelective(User record);

    User selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}
<?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="top.cairbin.test5.mapper.UserMapper">
  <resultMap id="BaseResultMap" type="top.cairbin.test5.dao.User">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="password" jdbcType="VARCHAR" property="password" />
    
    <collection property="ordersList" column="id" ofType="Orders" 
		     select="top.cairbin.test5.mapper.OrdersMapper.findOrdersWithUser">
	</collection>

    
  </resultMap>
  <sql id="Base_Column_List">
    id, name, password
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from user
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.User">
    insert into user (id, name, password
      )
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.User">
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="password != null">
        password,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.User">
    update user
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.User">
    update user
    set name = #{name,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

最后OrdersMapperOrdersMapper.xml

package top.cairbin.test5.mapper;

import top.cairbin.test5.dao.Orders;

public interface OrdersMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Orders record);

    int insertSelective(Orders record);

    Orders selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Orders record);

    int updateByPrimaryKey(Orders record);
}
<?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="top.cairbin.test5.mapper.OrdersMapper">
  <resultMap id="BaseResultMap" type="top.cairbin.test5.dao.Orders">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="number" jdbcType="VARCHAR" property="number" />
    <result column="user_id" jdbcType="INTEGER" property="userId" />
  </resultMap>
  <sql id="Base_Column_List">
    id, number, user_id
  </sql>
  
  <select id="findOrdersWithUser" parameterType="Integer" 
              resultMap="BaseResultMap">
		select * from orders WHERE user_id=#{id}	
	</select>

  
  
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from orders
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from orders
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="top.cairbin.test5.dao.Orders">
    insert into orders (id, number, user_id
      )
    values (#{id,jdbcType=INTEGER}, #{number,jdbcType=VARCHAR}, #{userId,jdbcType=INTEGER}
      )
  </insert>
  <insert id="insertSelective" parameterType="top.cairbin.test5.dao.Orders">
    insert into orders
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="number != null">
        number,
      </if>
      <if test="userId != null">
        user_id,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="number != null">
        #{number,jdbcType=VARCHAR},
      </if>
      <if test="userId != null">
        #{userId,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="top.cairbin.test5.dao.Orders">
    update orders
    <set>
      <if test="number != null">
        number = #{number,jdbcType=VARCHAR},
      </if>
      <if test="userId != null">
        user_id = #{userId,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="top.cairbin.test5.dao.Orders">
    update orders
    set number = #{number,jdbcType=VARCHAR},
      user_id = #{userId,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

我们编写测试类,在src/test/java下的top.cairbin.test5

PersonTest类来测试一对一的关系

package top.cairbin.test5;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import top.cairbin.test5.dao.Person;
import top.cairbin.test5.util.*;

public class PersonTest {
	@Test
    public void findPersonByIdTest() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MyBatisHelper.getSession();
        // 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
        Person person = session.selectOne("top.cairbin.test5.mapper." 
                                   + "PersonMapper.selectByPrimaryKey", 1);
        // 3、输出查询结果信息
        System.out.println(person);
        // 4、关闭SqlSession
        session.close();
    }

	//测试一对一(嵌套结果):
	@Test
    public void findPersonByIdTest2() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MyBatisHelper.getSession();
        // 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
        Person person = session.selectOne("top.cairbin.test5.mapper." 
                                   + "PersonMapper.findPersonById2", 1);
        // 3、输出查询结果信息
        System.out.println(person);
        // 4、关闭SqlSession
        session.close();
    }
}

点击运行,两个方法所用时间差距不小。

我们再编写测试类UserTest来测试一对多

package top.cairbin.test5;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import top.cairbin.test5.dao.User;
import top.cairbin.test5.util.MyBatisHelper;

public class UserTest {
	@Test
    public void findUserTest() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MyBatisHelper.getSession();
        // 2、查询id为1的用户信息,注意包名为mapper层的
        User user = session.selectOne("top.cairbin.test5.mapper."
                                + "UserMapper.selectByPrimaryKey", 1);
        // 3、输出查询结果信息
        System.out.println(user);
        // 4、关闭SqlSession
        session.close();
    }

}

最后编写OrdersTest来测试多对多

package top.cairbin.test5;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import top.cairbin.test5.dao.Orders;
import top.cairbin.test5.util.MyBatisHelper;

public class OrdersTest {
	@Test
    public void findOrdersTest(){
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MyBatisHelper.getSession();
        // 2、查询id为1的订单中的商品信息
        Orders orders = session.selectOne("top.cairbin.test5.mapper."
                               + "OrdersMapper.selectByPrimaryKey", 1);
        // 3、输出查询结果信息
        System.out.println(orders);
        // 4、关闭SqlSession
        session.close();
    }
}

总结

在本章节,我们学习了MyBatis的关联映射。此外,你会发现我们写代码不再像以前一样只放在一个包里,而是创建好几个子包分层放置不同的代码,这有利于代码逻辑清晰并且方便维护,这种分层设计已经有一个正式项目的雏形了,当你写完这些东西的时候项目目录应该与我差不多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1562942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑常见故障检测方法与对应问题分析说明

电脑常见故障检测方法与对应问题分析说明 前言说明1、机器无法开机故障2、屏幕无法显示3、无法联网4、能开机但是无法进入系统&#xff0c;提示not boot5、USB接口无法识别U盘 前言说明 本文为小白向&#xff0c;许多内容属于经验学而非科学&#xff0c;还望大佬们轻喷。 如上…

Verilog语法之always语句学习

always语法是Verilog_HDL中最常用的一种语法。 always过程语句和语句块组成的&#xff0c;语法格式如下所示。 always(敏感信号1 or 敏感信号2.....) always实现组合逻辑和时序逻辑。用always实现组合逻辑要将所有的敏感信号加入敏感列表中&#xff1b;用always实现时序逻辑时…

为什么都说”一入Java深似海“?

引言 在当今数字化时代&#xff0c;编程已经成为一项至关重要的技能。而在众多编程语言中&#xff0c;Java以其广泛的应用领域和强大的功能特性&#xff0c;吸引了无数开发者的目光。无论是Web开发、移动应用还是大数据处理&#xff0c;Java都发挥着举足轻重的作用。然而&…

GDAL源码剖析(一)

GDAL源码剖析&#xff08;一&#xff09;_gdal 源码-CSDN博客 一、GDAL简介 GDAL官方网站http://www.gdal.org/&#xff0c;本文章中的基本内容都是参照官网中的信息&#xff0c;如有错误或者与官网中的内容冲突&#xff0c;以官网中的为正确。 在开始文章之前&#xff0c;我…

探索数字物流技术 2024中国国际展览会与您相约七月杭州

数字贸易创新引领合作动能 《十四五规划》明确指出关于“加快数字化发展&#xff0c;建设数字中国”要求&#xff0c;积极为全国数字物流链转型革新试水探路。全力发展以数字化为引领的现代产业体系,打造面向未来、全球的数字物流技术变革高地。数字化成为了物流和供应链企业推…

Redis实战(黑马点评:短信登录)

1.基于Session实现发送短信验证码 UserController: /*** 发送手机验证码*/PostMapping("code")public Result sendCode(RequestParam("phone") String phone, HttpSession session) {return userService.sedCode(phone,session);}UserServiceImpl: Overri…

[yolox]ubuntu上部署yolox的ncnn模型

首先转换pytorch->onnx->param模型&#xff0c;这个过程可以查资料步骤有点多&#xff0c;参考blog.51cto.com/u_15660370/6408303&#xff0c;这里重点讲解转换后部署。 测试环境&#xff1a; ubuntu18.04 opencv3.4.4(编译过程省略&#xff0c;参考我其他博客) 安装…

一个页面实现两个滚动条【前端】

一个页面实现两个滚动条【前端】 前言版权推荐一个页面实现两个滚动条最后 前言 2024-4-2 12:54:46 以下内容源自《【前端】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN日星月云 博客主页是https://jsss-1.blog.csdn.net …

25.死锁

一个线程如果需要同时获取多把锁&#xff0c;就容易产生死锁。 t1线程获得A对象锁&#xff0c;接下来想获取B对象的锁。 t2线程获得B对象锁&#xff0c;接下来想获取A对象的锁。 /*** 死锁demo* param args*/public static void main(String[] args) {Object a new Object(…

数字医疗:智慧医共体引领健康未来

随着科技的不断发展&#xff0c;数字医疗正在成为医疗行业的一场革命。数字化技术的应用不仅提高了医疗服务的效率和质量&#xff0c;还为人们带来了更便捷、智能的健康管理方式。在这个数字化时代&#xff0c;智慧医共体已经成为了健康未来的引领者。 数字医疗&#xff0c;顾…

超图新建三维数据集继续学习

1 新建三维数据集 之前操作过新建三维数据集&#xff0c;还不熟悉&#xff0c;继续熟悉&#xff1b; 现在有一个文件型的数据源&#xff0c;名为swtest1&#xff1b;它前面小图标上有UDX三个字母&#xff0c;表明这是一个UDX类型的数据源&#xff1b;在此数据源上右击&#x…

研发效能·创享大会—IDCF五周年专场

时光流转&#xff0c;IDCF即将迎来五周年的庆典。在这个意义非凡的时刻&#xff0c;我们精心筹备了一场盛大的聚会【研发效能创享大会—IDCF五周年专场】。 IDCF自2019年成立以来&#xff0c;携手百余位技术领头人共同打造DevOps技术学习平台&#xff0c;与30万社群伙伴联动&a…

如何改写出优质文案,AI写作工具有方法

在当今数字化时代&#xff0c;内容创作已成为企业和个人在市场竞争中脱颖而出的关键因素。而写作优质文案是吸引读者注意力、传达信息以及促使行动的重要手段之一。然而&#xff0c;对许多人来说&#xff0c;写作可能是一项具有挑战性的任务。幸运的是&#xff0c;随着人工智能…

提升你的CSS技能:深入理解伪类选择器和伪元素选择器!

在CSS的世界里&#xff0c;有些选择器并不像它们的名字那样直接。今天&#xff0c;我们要探索的是两种特殊的选择器&#xff1a;伪类选择器和伪元素选择器。它们虽然名字相似&#xff0c;但功能和用途却大有不同。 下面就让我们一起来了解一下它们是如何在我们的页面布局中扮演…

EasyDarwin 、ffmpeg 音视频推流拉流;OBS视频推理软件、obs-rtspserver服务器;python读取rtsp流

参考&#xff1a;https://blog.csdn.net/N71FS1/article/details/130019563 一、EasyDarwin ffmpeg ffmpeg 推送音视频流到rtsp流服务器 EasyDarwin 作为rtsp流服务器 &#xff08;下载&#xff1a;https://www.easydarwin.org/p/easydarwin.html&#xff09;OBS 直播音视频录…

什么是交换机虚拟化技术?

热门IT【视频教程】-华为/思科/红帽/oracle https://blog.csdn.net/XMWS_IT/article/details/137153651?spm1001.2014.3001.5501 简介 通过交换机虚拟化技术&#xff0c;既可以在逻辑上集成多台物理连接的交换机&#xff0c;实现拓宽虚拟交换机带宽、提升转发效率的目的&…

城市交通视频视频联网系统实施方案

目录 1.需求调研 2.系统设计 3.技术分析 4.技术开发 5.系统平台环境要求 6.网络要求 7.安全要求 8.项目交付和验收 8.1交付准备 8.2系统安装、培训 8.2.1系统验收 8.2.2项目进度计划 附录&#xff1a;交通监控设备情况调研表 1.需求调研 从SZ市交通运输局、以及下…

YOLOv9改进策略 :主干优化 | 无需TokenMixer也能达成SOTA性能的极简ViT架构 | CVPR2023 RIFormer

💡💡💡本文改进内容: token mixer被验证能够大幅度提升性能,但典型的token mixer为自注意力机制,推理耗时长,计算代价大,而RIFormers是无需TokenMixer也能达成SOTA性能的极简ViT架构 ,在保证性能的同时足够轻量化。 💡💡💡RIFormerBlock引入到YOLOv9,多个数…

【Linux】自定义协议+序列化+反序列化

自定义协议序列化反序列化 1.再谈 "协议"2.Cal TCP服务端2.Cal TCP客户端4.Json 喜欢的点赞&#xff0c;收藏&#xff0c;关注一下把&#xff01; 1.再谈 “协议” 协议是一种 “约定”。在前面我们说过父亲和儿子约定打电话的例子&#xff0c;不过这是感性的认识&a…

Java接口与继承实践:Ether通信系统的构建(day16)

创建一个接口Icontroller, 再创建一个接口IReceiver, 创建一个子类实现IReceiver&#xff0c; 创建一个子类实现IContrller&#xff0c; 创建一个类Ether 创建一个Signal类 创建一个类Radiosignal继承Signal 创建一个用户User 最后创建一个Main类 今日总结&#xff1a…