返回 List(多条记录)
/** * 查询所有的汽车信息 * * @return 所有的汽车信息 */ List<Car> selectAll();
<select id="selectAll" resultType="car"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car; </select>
@org.junit.Test public void testSelectAll() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); List<Car> cars = mapper.selectAll(); cars.forEach(System.out::println); SqlSessionUtil.close(); }
- 如果返回的结果集只有一条记录,可以使用集合进行接收
- 如果返回的结果集有多条记录,只能使用集合进行接收,如果返回的结果集只有一条记录,可以使用集合进行接收也可以使用一个pojo进行接收
返回 Map
- 当返回的数据,没有合适的实体类对应的话,可以采用Map集合接收,字段名做key,字段值做value,如果SQL语句中使用了别名,则使用指定的别名做key
- 查询如果可以保证只有一条数据,则返回一个Map集合即可。如果返回的数据存在多条,则使用一个Map集合接收会报错,得使用Map组成的List集合进行接收
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZqbNusc-1685870936829)(https://www.yuque.com/api/filetransfer/images?url=https%3A%2F%2Fucc.alicdn.com%2Fimages%2Fuser-upload-01%2F63cfeac812cf4a99a1381937b72343bf.png&sign=2b687760bd7f818d690380fb59baf7e89531b0ad5e79ba1e9630c4d78948a06f#from=url&height=225&id=N4UXP&originHeight=313&originWidth=316&originalType=binary&ratio=1.25&rotation=0&showTitle=false&status=done&style=none&title=&width=227)]
/** * 根据id查询汽车信息 * * @param id 汽车信息的id * @return 汽车信息封装成的Map */ Map<String, Object> selectByIdReturnMap(Long id);
<!-- MyBatis 中 map 为 java.util.Map 的别名 --> <select id="selectByIdReturnMap" resultType="map"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car where id = #{id}; </select>
@org.junit.Test public void testSelectByIdReturnMap() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Map<String, Object> map = mapper.selectByIdReturnMap(5L); System.out.println(map); SqlSessionUtil.close(); }
返回 List<Map>
- 查询结果条数大于等于1条数据,没有合适的实体类对应的话,则可以返回一个存储Map集合的List集合。
List<Map>
相当于List<Car>
- 查询出来的数据有多条或者只有一条都可以使用存储Map集合的List集合进行接收
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ET4Etots-1685870936830)(https://www.yuque.com/api/filetransfer/images?url=https%3A%2F%2Fucc.alicdn.com%2Fimages%2Fuser-upload-01%2F41b7c6ebf4454d82b5a8e61d75f06698.png&sign=164d10c96d9a58c55ad0984c21efae7c611f5c3cdc9f43da16de37ccc6fb26bb#from=url&height=381&id=Gbi57&originHeight=733&originWidth=477&originalType=binary&ratio=1.25&rotation=0&showTitle=false&status=done&style=none&title=&width=248)]
/** * 查询所有的汽车信息 * * @return 由汽车信息封装在Map中组成的List集合 */ List<Map<String, Object>> selectAllReturnListMap();
<!-- MyBatis 中 map 为 java.util.Map 的别名 --> <!-- 返回的还是 map,只有最后数据多个map封装在list中 --> <select id="selectAllReturnListMap" resultType="map"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car; </select>
@org.junit.Test public void testSelectAllReturnListMap() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); List<Map<String, Object>> maps = mapper.selectAllReturnListMap(); maps.forEach(System.out::println); SqlSessionUtil.close(); }
返回 Map<String, Map>
- 当查询结果集中存在多条数据记录,使用
List<Map>
进行接收,不利于我们对结果集中的数据进行查询,需要顺序遍历查询 - 为了可以更快的查询我们所需的数据,我们可以拿数据记录的id(主键)做key,由整条数据记录封装而成的Map作为value,则以后取出对应的所需数据的Map集合时更方便。
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XHoQiYeX-1685870936832)(https://www.yuque.com/api/filetransfer/images?url=https%3A%2F%2Fucc.alicdn.com%2Fimages%2Fuser-upload-01%2F78116385c1a742ac9862719ae9d2635d.png&sign=f48795a8beb121c5ffb9d5e63f0f160f78d5104ed3b2f7c3b863e2ea13231504#from=url&height=311&id=zwM3Y&originHeight=736&originWidth=787&originalType=binary&ratio=1.25&rotation=0&showTitle=false&status=done&style=none&title=&width=332.4000244140625)]
/** * 查询所有的汽车信息 * * @return 由汽车信息封装在Map中组成的Map集合 */ @MapKey("id") // @MapKey 注解的属性 value 指定使用数据哪个字段作为Map 的 key // 作为大Map key 的数据类型要与@MapKey 注解指定的字段的数据类型一致 Map<Long, Map<String, Object>> selectAllReturnMapMap();
<!-- MyBatis 中 map 为 java.util.Map 的别名 --> <!-- 返回的还是 map,只有最后数据多个map封装在Map中 --> <select id="selectAllReturnMapMap" resultType="map"> select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car; </select>
@org.junit.Test public void testSelectAllReturnMapMap() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Map<Long, Map<String, Object>> map = mapper.selectAllReturnMapMap(); System.out.println(map.get(5L)); System.out.println(map.get(7L)); SqlSessionUtil.close(); }
结果映射
- 当查询结果的列名和 java 对象的属性名对应不上时的解决方式:
- 第一种方式:as 给列起别名
- 第二种方式:使用resultMap进行结果映射
- 第三种方式:是否开启驼峰命名自动映射(配置settings)
使用 resultMap 进行结果映射
- resultMap 可以实现查询结果集中字段名和Java对象的属性名之间的映射
/** * 查询所有的汽车信息 * 使用 ResultMap 标签进行结果映射 * * @return 汽车信息组成的集合 */ List<Car> selectAllByResultMap();
<!-- 定义一个结果映射 在这个结果映射中指定数据库表字段和Java类的属性名之间的对应关系 type="":用于指定Java类的类名 id="":指定 resultMap 的唯一标识,这个id要在select标签中进行使用 --> <!-- 在Mybatis核心配置文件中指定了别名,所以可以直接使用car --> <resultMap id="carResultMap" type="car"> <!-- 如果数据库表中有主键,建议配一个id标签,提高Mybatis的执行效率 --> <!-- 当然 id 也可以使用 result 标签,就是效率较低 --> <id property="id" column="id"/> <!-- property="":填写Java类的属性名 column="":填写数据库表的字段名 javaType:指定Java类属性的类型,不用Mybatis自动类型推断,提高效率(可以使用别名) jdbcType:指定数据库表字段的类型,不用Mybatis自动类型推断,提高效率 --> <result property="carNum" column="car_num" javaType="java.lang.String" jdbcType="VARCHAR" /> <!-- 如果column和property的属性值一样可以省略 --> <!-- <result property="brand" column="brand"/> --> <result property="guidePrice" column="guide_price"/> <result property="produceTime" column="produce_time"/> <result property="carType" column="carType" javaType="string" jdbcType="VARCHAR" /> </resultMap> <!-- 使用结果映射,在select标签中不使用resultType 而是使用 resultMap,其属性值为 resultMap 的 id 使用 resultMap 指定结果映射 --> <select id="selectAllByResultMap" resultMap="carResultMap"> select * from t_car; </select>
@org.junit.Test public void testSelectAllByResultMap() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); List<Car> cars = mapper.selectAllByResultMap(); cars.forEach(System.out::println); SqlSessionUtil.close(); }
开启驼峰命名自动映射
- 驼峰命名自动映射这种方式的前提是:Java类的属性名遵循Java的命名规范,数据库表的列名遵循SQL的命名规范。
- Java命名规范:首字母小写,后面每个单词首字母大写,遵循驼峰命名方式。
- SQL命名规范:全部小写,单词之间采用下划线分割。
- Java类的属性名与数据库表的列名的对应关系:
| 实体类中的属性名 | 数据库表的列名 |
| — | — |
| carNum | car_num |
| carType | car_type |
| produceTime | produce_time | - 开启驼峰命名自动映射,在MyBatis的核心配置文件中的settings标签中进行配置
- MyBatis 中文网 settings 配置说明:https://mybatis.net.cn/configuration.html#settings
<settings> <!-- 开启驼峰命名自动映射 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
/** * 查询所有汽车信息 * 使用驼峰命名自动映射 * * @return 汽车信息组成的集合 */ List<Car> selectAllByMapUnderscoreToCamelCase();
<select id="selectAllByMapUnderscoreToCamelCase" resultType="car"> select * from t_car; </select>
@org.junit.Test public void testSelectAllByMapUnderscoreToCamelCase() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); List<Car> cars = mapper.selectAllByMapUnderscoreToCamelCase(); cars.forEach(System.out::println); SqlSessionUtil.close(); }
返回总记录条数
/** * 查询汽车信息的总记录条数 * * @return 汽车信息的总记录条数 */ Long selectTotal();
<!-- long 是 java.util.Long 的别名 --> <select id="selectTotal" resultType="long"> select count(*) from t_car; </select>
@org.junit.Test public void testSelectTotal() { SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Long total = mapper.selectTotal(); System.out.println(total); SqlSessionUtil.close(); }
动态 SQL
业务场景(为什么需要动态SQL)
- 我们需要进行数据的批量删除
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2HD5LXTw-1685870936837)(https://www.yuque.com/api/filetransfer/images?url=https%3A%2F%2Fucc.alicdn.com%2Fimages%2Fuser-upload-01%2F7dcef7f1f04e44bf8f7431c7a5e87bdd.png&sign=9532cda95213becdabf7a702b5cadecf196a083af802d074aa92c11792567342#from=url&height=109&id=sPcVI&originHeight=168&originWidth=232&originalType=binary&ratio=1.25&rotation=0&showTitle=false&status=done&style=none&title=&width=150)]
delete from t_car where id in(1,2,3,4,5,6,...);
,其中,SQL语句中的in()
中的内容是动态的,根据用户选择的id不同,SQL语句in()
中的内容是不同的
- 我们需要进行多条件查询
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EzjhAMts-1685870936838)(https://www.yuque.com/api/filetransfer/images?url=https%3A%2F%2Fucc.alicdn.com%2Fimages%2Fuser-upload-01%2Fd56eb25cb21b43a39ad5fb938d6659d0.png&sign=4557fedb9e295ef872fcccf3a5b57265041fcbeeb0a4d48807994f5cf1be35fa#from=url&height=92&id=Pr2m3&originHeight=159&originWidth=706&originalType=binary&ratio=1.25&rotation=0&showTitle=false&status=done&style=none&title=&width=410.4000244140625)]
select * from t_car where brand like '丰田%' and guide_price > 30 and .....;
,其中,SQL语句中where后面条件的个数是不确定的,是动态的,用户选择不同的条件,SQL语句中条件的个数不同
if 标签
- 可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)
/** * 多条件查询 * 可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type) * * @param brand 品牌 * @param guidePrice 指导价格 * @param carType 汽车类型 * @return 汽车信息组成的集合 */ List<Car> selectByMultiCondition( @Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType );
<select id="selectByMultiCondition" resultType="Car"> <!-- where 1 = 1 保证条件都为空时sql语法可以通过 --> <!-- 如果条件都为空,并且没有1 = 1,则SQL语句会变为select * from t_car where, 会报语法错误 --> select * from t_car where 1 = 1 <!-- 1. if标签中test属性是必须的。 2. if标签中test属性的值是false或者true。 if标签的test属性中可以写表达式,值为false或者true 3. 如果test是true,则if标签中的sql语句就会拼接。反之,则不会拼接。 4. 在test属性中使用接口方法中参数的方式:(与#{}中使用接口方法中参数一样) 1)当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。 @Param("brand"),那么这里只能使用brand 2)当没有使用@Param注解,那么test中要出现的是: param1 param2 param3 arg0 arg1 arg2.... 3)当使用了POJO,那么test中出现的是POJO类的属性名。 5. 在mybatis的动态SQL当中,不能使用&&,只能使用and。 --> <!-- 第一个条件添加and防止“where 1 = 1 brand like "%"#{brand}"%"”语法错误 --> <if test="brand != null and brand != ''"> and brand like "%"#{brand}"%" </if> <if test="guidePrice != null and guidePrice != ''"> and guide_price > #{guidePrice} </if> <if test="carType != null and carType != ''"> and car_type = #{carType} </if> </select>
@Test public void testSelectByMultiCondition(){ SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); // 假设三个条件都不是空 //List<Car> cars = mapper.selectByMultiCondition("比亚迪", 2.0, "新能源"); // 假设三个条件都是空 //List<Car> cars = mapper.selectByMultiCondition("", null, ""); // 假设后两个条件不为空,第一个条件为空 //List<Car> cars = mapper.selectByMultiCondition("", 2.0, "新能源"); // 假设第一个条件不是空,后两个条件是空 List<Car> cars = mapper.selectByMultiCondition("比亚迪", null, ""); cars.forEach(car -> System.out.println(car)); sqlSession.close(); }
where 标签
- where标签的作用:让where子句更加动态智能。当所有条件都为空时,where标签保证不会生成where子句,可以自动去除某些条件前面多余的and或or,但是不能自动去除某些条件后面多余的and或or
/** * 使用where标签,让where子句更加的智能。 * @param brand * @param guidePrice * @param carType * @return */ List<Car> selectByMultiConditionWithWhere(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);
<select id="selectByMultiConditionWithWhere" resultType="Car"> select * from t_car <!-- where标签是专门负责where子句动态生成的。 如果where标签中的条件都不成立,则SQL语句中不会有where子句 --> <where> <!-- 可以自动去除条件前面多余的and或or --> <if test="brand != null and brand != ''"> and brand like "%"#{brand}"%" </if> <if test="guidePrice != null and guidePrice != ''"> and guide_price > #{guidePrice} </if> <if test="carType != null and carType != ''"> and car_type = #{carType} </if> </where> </select>
@Test public void testSelectByMultiConditionWithWhere(){ SqlSession sqlSession = SqlSessionUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); // 三个条件都不是空 //List<Car> cars = mapper.selectByMultiConditionWithWhere("比亚迪", 2.0, "新能源"); // 三个条件都是空 //List<Car> cars = mapper.selectByMultiConditionWithWhere("", null, ""); // 如果第一个条件是空 //List<Car> cars = mapper.selectByMultiConditionWithWhere("", 2.0, "新能源"); // 后面两个条件是空 List<Car> cars = mapper.selectByMultiConditionWithWhere("比亚迪", null, ""); cars.forEach(car -> System.out.println(car)); sqlSession.close(); }
trim 标签
<select id="selectByMultiConditionWithTrim" resultType="Car"> select * from t_car <!-- prefix:加前缀 suffix:加后缀 prefixOverrides:删除前缀 suffixOverrides:删除后缀 --> <!-- prefix="where" 是在trim标签内容的前面添加 where, 这个添加是动态的 如果有条件,会动态添加where,没有则不添加 --> <!-- suffixOverrides="and|or" 把trim标签中动态判断完后的内容多余的后缀and或or去掉 --> <trim prefix="where" suffixOverrides="and|or"> <if test="brand != null and brand != ''"> brand like "%"#{brand}"%" or </if> <if test="guidePrice != null and guidePrice != ''"> guide_price > #{guidePrice} and </if> <if test="carType != null and carType != ''"> car_type = #{carType} </if> </trim> </select>
set 标签
- 主要使用在update语句当中,用来动态生成set关键字,同时去掉最后多余的“,”
- 需求:只更新提交的不为空的字段,如果提交的数据是空或者"“,那么这个字段我们将不更新,即字段不为空或者”"就动态拼接其对应的SQL子句,否则不动态拼接其对应的SQL子句
/** * 更新信息,使用set标签 * @param car * @return */ int updateWithSet(Car car);
<update id="updateBySet"> update t_car <set> <if test="carNum != null and carNum != ''">car_num = #{carNum},</if> <if test="brand != null and brand != ''">brand = #{brand},</if> <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if> <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if> <if test="carType != null and carType != ''">car_type = #{carType},</if> </set> where id = #{id} </update>
choose when otherwise
这三个标签是必须在一起使用的:
<choose> <when></when> <when></when> <when></when> <otherwise></otherwise> </choose>
等同于:
if(){ }else if(){ }else if(){ }else if(){ }else{ }
只有一个分支会被选择!!!!
需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据汽车类型查询。
/** * 使用choose when otherwise标签查询 * @param brand * @param guidePrice * @param produceTime * @return */ List<Car> selectWithChoose(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType);
<select id="selectByChoose" resultType="Car"> select * from t_car <where> <!-- 先根据品牌查询,没有传品牌,在根据价格查询, 都没有最后根据汽车类型查询 --> <choose> <!--只有一个分支会执行,所以不需要and or关键字--> <when test="brand != null and brand != ''"> brand like "%"#{brand}"%" </when> <when test="guidePrice != null and guidePrice != ''"> guide_price > #{guidePrice} </when> <!--都为null,还是执行这个分支,car_type = null,只是查不到数据--> <otherwise> car_type = #{carType} </otherwise> </choose> </where> </select>
foreach 标签
- 循环数组或集合,动态生成sql,比如这样的SQL:
delete from t_car where id in(1,2,3); delete from t_car where id = 1 or id = 2 or id = 3;
insert into t_car values (null,'1001','凯美瑞',35.0,'2010-10-11','燃油车'), (null,'1002','比亚迪唐',31.0,'2020-11-11','新能源'), (null,'1003','比亚迪宋',32.0,'2020-10-11','新能源')
批量删除
in()
/** * 批量删除。foreach标签 * @param ids * @return */ int deleteByIds(@Param("ids") Long[] ids);
<!-- foreach标签的属性: collection:指定数组或者集合 item:代表数组或集合中的元素 separator:循环之间的分隔符,自动添加分隔符,会自动在分隔符的两边添加空格 open: foreach循环拼接的所有sql语句的最前面以什么开始。 close: foreach循环拼接的所有sql语句的最后面以什么结束。 --> <delete id="deleteByIds"> <!-- delete from t_car where id in( <foreach collection="ids" item="aaaaaaa" separator=","> #{aaaaaaa} </foreach> ) 没有使用@Param注解,上面的SQL报错了,错误信息是:[array, arg0] 因为没有使用@Param注解时,参数在map集合中存储,默认使用array, arg0作为key map.put("array", 数组); map.put("arg0", 数组); --> delete from t_car where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete>
or
/** * 根据id批量删除 使用or关键字。 * @param ids * @return */ int deleteByIds2(@Param("ids") Long[] ids);
<delete id="deleteByIds2"> delete from t_car where <!-- 会自动在分隔符的两边添加空格 --> <foreach collection="ids" item="id" separator="or"> id=#{id} </foreach> </delete>
批量插入
/** * 批量插入,一次插入多条Car信息 * @param cars * @return */ int insertBatch(@Param("cars") List<Car> cars);
<insert id="insertBatch"> insert into t_car values <!-- cars 汽车信息组成的list集合,car一个汽车类的对象,取属性,对象.属性 --> <foreach collection="cars" item="car" separator=","> (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType}) </foreach> </insert>
sql 标签与 include 标签
- sql标签用来声明sql片段,可以使需要重复编写的重复的SQL语句片段可以得到复用
- include标签用来将声明的sql片段包含到某个sql语句当中
- 作用:代码复用,易维护。
<!-- 声明sql片段 将重复的SQL片段提取出来 --> <sql id="carCols"> id, car_num carNum, brand, guide_price guidePrice, produce_time produceTime, car_type carType </sql> <select id="selectAllRetMap" resultType="map"> <!-- 将声明的sql片段包含进来 --> select <include refid="carCols"/> from t_car </select> <select id="selectAllRetListMap" resultType="map"> select <include refid="carCols"/> carType from t_car </select> <select id="selectByIdRetMap" resultType="map"> select <include refid="carCols"/> from t_car where id = #{id} </select>
MyBatis的高级映射及延迟加载
- 低级映射(基础映射):一个数据库表对应一个Java对象
- 高级映射:数据存储在数据库中两张不同的表中,并两个表之间的数据之间具有关系,此时映射到Java对象上为高级映射
数据库表
use mybatis_study; drop table t_clazz; create table t_clazz( cid int primary key, cname varchar(255) ); drop table t_student; create table t_student( sid int primary key, sname varchar(255), cid int ); insert into t_clazz values (1000, '高三一班'), (1001, '高三二班'); insert into t_student values (1, '张三', 1000), (2, '李四', 1000), (3, '王五', 1000), (4, '赵六', 1001), (5, '钱七', 1001);
依赖
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
项目结构
实体类
package cw.study.mybatis.pojo; /** * ClassName: Clazz * Package: cw.study.mybatis.pojo * Description: * 班级信息 * * @Author tcw * @Create 2023-06-04 11:38 * @Version 1.0 */ public class Clazz { private Integer cid; private String cname; public Clazz() { } public Clazz(Integer cid, String cname) { this.cid = cid; this.cname = cname; } @Override public String toString() { return "Clazz{" + "cid=" + cid + ", cname='" + cname + '\'' + '}'; } 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; } }
package cw.study.mybatis.pojo; /** * ClassName: Student * Package: cw.study.mybatis.pojo * Description: * 学生信息 * * @Author tcw * @Create 2023-06-04 11:38 * @Version 1.0 */ public class Student { private Integer sid; private String sname; public Student() { } public Student(Integer sid, String sname) { this.sid = sid; this.sname = sname; } @Override public String toString() { return "Student{" + "sid=" + sid + ", sname='" + sname + '\'' + ", " + '}'; } 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; } }
多对一
- 主表与副表:谁在前,谁就是主表
- 多对一,多为主表
- 一对多,一为主表
- 主表对应Java中的主对象
- 多对一,多个学生对应一个班级,学生表为主表,学生对象为主对象,班级对象为副对象,要建立两个对象之间的关系,通过学生对象可以找到班级对象,所以在学生类中添加对班级对象的引用属性
- 多对一的映射实体类设计:
- 修改学生类,添加对班级对象的引用属性,修改setter、getter、toString
/** * 学生信息 */ public class Student { // Student是多的一方 private Integer sid; private String sname; private Clazz clazz; // Clazz是一的一方。 ...... }
/** * 班级信息 */ public class Clazz { private Integer cid; private String cname; ...... }