mybatis 一对一,一对多
- 需求:实现一个产品对应一个产品类别,一个产品对应多张图片的查询。
- 数据库
总共3个表,picture(图片表),Product(产品表),Producttype(产品类别表)
-- picture(图片表)
CREATE TABLE `picture` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`level` int(11) DEFAULT NULL COMMENT '级别',
`title` varchar(255) DEFAULT NULL COMMENT '标题',
`updateTime` datetime DEFAULT NULL COMMENT '更新时间',
`url` varchar(255) DEFAULT NULL COMMENT '地址',
`updateAdmin_name` varchar(50) DEFAULT NULL COMMENT '更新者姓名',
`product_id` int(11) DEFAULT NULL COMMENT '商品id',
PRIMARY KEY (`id`) USING BTREE,
KEY `FKf820vwoskrv05yxj80mlbj226` (`updateAdmin_name`) USING BTREE,
KEY `product_pic` (`product_id`),
CONSTRAINT `product_pic` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='图片表';
-- Product(产品表)
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(255) DEFAULT NULL COMMENT '商品编码',
`title` varchar(255) DEFAULT NULL COMMENT '名称',
`price` double(11,0) DEFAULT NULL COMMENT '价格',
`note` varchar(255) DEFAULT NULL COMMENT '描述',
`stock` bigint(20) DEFAULT NULL COMMENT '库存',
`recommend` tinyint(2) DEFAULT NULL COMMENT '推荐',
`turnover` int(255) DEFAULT NULL COMMENT '成交量',
`hot` tinyint(2) DEFAULT NULL COMMENT '(0不热门1热门)',
`unit` varchar(30) DEFAULT NULL COMMENT '单位',
`Star` tinyint(255) DEFAULT NULL COMMENT '星级(0-5)',
`createTime` datetime DEFAULT NULL COMMENT '创建时间',
`updateAdmin_name` varchar(50) DEFAULT NULL COMMENT '管理员姓名',
`type_id` int(11) DEFAULT NULL COMMENT '类别id',
PRIMARY KEY (`id`) USING BTREE,
KEY `FK96wxe8531cmahwxjoen492n2h` (`updateAdmin_name`) USING BTREE,
KEY `FKklsdhflskdhfl5s468ytr131j3hg` (`type_id`) USING BTREE,
CONSTRAINT `FKklsdhflskdhfl5s468ytr131j3hg` FOREIGN KEY (`type_id`) REFERENCES `producttype` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='商品表';
-- Producttype(产品类别表)
CREATE TABLE `producttype` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT '类别名称',
`status` tinyint(2) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='商品类别';
-- 数据
INSERT INTO `picture` VALUES (1, 1, '可乐小图', '2019-10-06 17:58:10', '/aa/av/asda/adsd', 'admin', 1);
INSERT INTO `picture` VALUES (2, 2, '可乐大图', '2019-10-06 17:58:40', '/asd/ad/asd/asd/asd/asdas/d', 'admin', 1);
INSERT INTO `product` VALUES (1, '1001', '可乐', 5, '冰镇解渴', 300, 1, 250, 1, '瓶', 3, '2019-10-06 17:57:09', 'admin', 13);
INSERT INTO `producttype` VALUES (2, '水果', 2);
INSERT INTO `producttype` VALUES (4, '肉干鱼干类', 1);
INSERT INTO `producttype` VALUES (5, '口香糖类', 1);
INSERT INTO `producttype` VALUES (8, '休闲食品', 1);
INSERT INTO `producttype` VALUES (13, '饮品', 1);
INSERT INTO `producttype` VALUES (14, '饮料', 1);
- 实体类
这里用了lombok
@Data
public class Picture {
private Integer id;
/**
* 图片级别,(1首页图,2商品详情图)
*/
private Integer level;
/**
* 图片标题
*/
private String title;
private Date updateTime;
private String url;
/**
* 更新者,管理员
*/
private String updateAdminName;
private Integer productId;
@Data
public class Product {
private Integer id;
/**
* 商品编码
*/
private String code;
/**
* 名称
*/
private String title;
private Double price;
/**
* 描述
*/
private String note;
/**
* 库存
*/
private Long stock;
/**
* 是否推荐
*/
private Integer recommend;
/**
* 成交量
*/
private Integer turnover;
private Integer hot;
/**
* 单位
*/
private String unit;
/**
* 星级
*/
private Integer star;
private Date createTime;
/**
* 管理员姓名
*/
private String updateAdminName;
/**
* typeId
*/
private Producttype typeId;
/**
* 图片
*/
private List<Picture> picId;
}
@Data
public class Producttype {
private Integer id;
private String name;
private Integer status;
}
- ProductMapper.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.bysj.lsxsglxt.mapper.ProductMapper">
<resultMap id="BaseResultMap" type="com.bysj.lsxsglxt.model.Product">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="code" jdbcType="VARCHAR" property="code" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="price" jdbcType="DOUBLE" property="price" />
<result column="note" jdbcType="VARCHAR" property="note" />
<result column="stock" jdbcType="BIGINT" property="stock" />
<result column="recommend" jdbcType="TINYINT" property="recommend" />
<result column="turnover" jdbcType="INTEGER" property="turnover" />
<result column="hot" jdbcType="TINYINT" property="hot" />
<result column="unit" jdbcType="VARCHAR" property="unit" />
<result column="Star" jdbcType="TINYINT" property="star" />
<result column="createTime" jdbcType="TIMESTAMP" property="createTime" />
<result property="updateAdminName" jdbcType="VARCHAR" column="updateAdmin_name"/>
<association property="typeId" column="type_id" javaType="com.bysj.lsxsglxt.model.Producttype"
fetchType="lazy" select="com.bysj.lsxsglxt.mapper.ProducttypeMapper.showByIdType">
</association>
<collection column="id" property="picId" ofType="com.bysj.lsxsglxt.model.Picture"
select="com.bysj.lsxsglxt.mapper.PictureMapper.selectByProductId"
fetchType="lazy">
</collection>
</resultMap>
<select id="selectById" resultMap="BaseResultMap" parameterType="integer">
select id, code, title, price, note, stock, recommend, turnover, hot, unit, Star, createTime,
updateAdmin_name,type_id
from product
where product.id=#{id};
</select>
</mapper>
ProductMapper.java
public interface ProductMapper {
public Product selectById(Integer id);
}
核心
- 查询语句
select id, code, title, price, note, stock, recommend, turnover, hot, unit, Star, createTime,
updateAdmin_name,type_id
from product
where product.id=#{id};
- 一对一
<association property="typeId" column="type_id" javaType="com.bysj.lsxsglxt.model.Producttype"
fetchType="lazy" select="com.bysj.lsxsglxt.mapper.ProducttypeMapper.showByIdType">
</association>
- 一对多
<collection column="id" property="picId" ofType="com.bysj.lsxsglxt.model.Picture"
select="com.bysj.lsxsglxt.mapper.PictureMapper.selectByProductId"
fetchType="lazy">
</collection>
- com.bysj.lsxsglxt.mapper.ProducttypeMapper.showByIdType
public interface ProducttypeMapper {
/**
* 通过id查询
* @param id
* @return
*/
@Select("select * from productType WHERE id = #{id}")
public Producttype showByIdType(String id);
}
- com.bysj.lsxsglxt.mapper.PictureMapper.selectByProductId
public interface PictureMapper {
@Results(id = "selectByProductId",value = {
@Result(id=true,column = "id",property = "id"),
@Result(column = "level",property = "level"),
@Result(column = "title",property = "title"),
@Result(column = "updateTime",property = "updateTime"),
@Result(column = "url",property = "url"),
@Result(column = "updateAdmin_name",property = "updateAdminName"),
@Result(column = "product_id",property = "productId")
}
)
@Select("select * from picture where product_id=#{id}")
public Picture selectByProductId(Integer id);
@ResultMap(value = "selectByProductId")
@Select("select * from picture where id=#{id}")
public Picture selectById(Integer id);
}
- association的属性解释 property:实体类属性名,select:执行一个查询语句,查询的方法在一个文件中可以只写方法名(查询的id属性),column:做为select属性的条件,值填查询语句的type_id,FetchType属性:有2个(LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。),JavaType:实体类。
查询语句:
select id, code, title, price, note, stock, recommend, turnover, hot, unit, Star, createTime,
updateAdmin_name,type_id
from product
where product.id=#{id};
-
collection的属性解释 property,select,column和association,FetchType的属性一样,ofType和JavaType有一点相同,但是ofType是映射到list集合属性中pojo的类型
-
对@Results,@Result,@Select,@ResultMap注解的解释
@Results: 结果集的映射 有2个属性,id和value
@Result: 结果集映射的列 他的集合是@Results的value属性
@Select: 书写查询语句
@ResultMap 返回的映射集合,值填@Results的id
mybatis的注解详情查看---->点击查看
测试
@Autowired
private ProductMapper productMapper;
/**
* 查询id为1的产品
*/
Product product = productMapper.selectById(1);
System.out.println(product);
}
测试截图:
执行顺序
- 通过@Autowired自动注入ProductMapper。
- 执行productMapper.selectById(1)方法。
- 通过select * from product where product.id=1; 查询出 product.id(id)以及type_id这两个关键id。
- 通过 id 在一对一association标签中执行select="com.bysj.lsxsglxt.mapper.ProducttypeMapper.showByIdType"的方法对Producttype实体类赋值。
- 通过type_id 在一对多collection标签中执行select="com.bysj.lsxsglxt.mapper.PictureMapper.selectByProductId"的方法对list集合赋值。
注意事项
- 在Picture实体类中
private Integer productId;是Integer类型的不是product实体类类型
- 一对一(一对多的一样)
本例中
- sql语句->select * from product where product.id=1(单表查询)
- 使用select属性。执行showByIdType方法,对应的映射关系在showByIdType方法中
<association property="typeId" column="type_id" javaType="com.bysj.lsxsglxt.model.Producttype"
fetchType="lazy" select="com.bysj.lsxsglxt.mapper.ProducttypeMapper.showByIdType">
</association>
第二种方法
- sql语句(多表连接查询)
SELECT product.* ,
pt.id ptid,pt.`name`,pt.`status`,
pic.id picid,pic.`level`,pic.title pictitle,pic.updateTime,pic.url,pic.updateAdmin_name,pic.product_id
FROM product INNER JOIN producttype pt ON product.type_id = pt.id INNER JOIN picture pic ON pic.product_id = product.id
WHERE product.id = #{id}
- 在写映射关系
<association property="typeId" column="type_id" javaType="com.bysj.lsxsglxt.model.Producttype"
fetchType="lazy">
<id column="ptid" property="id" />
<result column="name" property="name"/>
<result column="status" property="status"/>
</association>
方法2的测试截图:
总结
- column对应的是数据库的字段,property对应的是实体类的属性
- javatype是指单个的实体类,oftype是指多个实体类(集合)
- 一对一用,一对多用
- 方法一和方法二选择一个用,不要一起用,方法一使用了多条sql语句,方法二只使用了一个sql语句