关联关系
- 一对一
- 一对多(一对多)(重点)
- 多对多
查询
添加(需要事务)
说明
保存跟我们单表保存是一样的,如果非要一次保存两个表的数据,需要在业务处理,需要开始事务
级联添加
mapper.xml
- 注意要返回主表的主键值
主表
<insert id="insert" keyProperty="product.pid" useGeneratedKeys="true">
INSERT INTO product (name, price)
VALUES (#{product.name}, #{product.price})
</insert>
从表
<insert id="insert">
INSERT INTO product_detail(ex, pid)
VALUES (#{pd.ex}, #{pd.pid});
</insert>
Mapper接口
public interface ProductDetailMapper {
int insert(@Param("pd") ProductDetail productDetail);
}
public interface ProductMapper {
int insert(@Param("product") Product product);
}
Service
@Service
public class IndexServiceImpl implements IndexService {
@Resource
ProductMapper productMapper;
@Resource
ProductDetailMapper productDetailMapper;
@Override
public int saveProduct(Product product) {
int insert = productMapper.insert(product);
ProductDetail productDetail = product.getProductDetail();
productDetail.setPid(product.getPid());
int insert1 = productDetailMapper.insert(productDetail);
return 0;
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-mybatis.xml"})
public class IndexServiceImplTest {
@Resource
IndexService indexService;
@Test
public void saveProduct() {
Product product = new Product();
product.setName("手机");
product.setPrice(new BigDecimal("9999.00"));
ProductDetail productDetail = new ProductDetail();
productDetail.setEx("测试数据");
product.setProductDetail(productDetail);
indexService.saveProduct(product);
}
}
一对多
分类跟商品 , 一级菜单跟二级菜单
级联保存
对象模型
@Data
public class Category {
private Integer cateId;
private String cateName;
private List<Product> products;
}
@Data
public class Product {
private Integer pid;
private String name;
private BigDecimal price;
private ProductDetail productDetail;
}
关系模型(外键字段)
CREATE TABLE category
(
cate_id int AUTO_INCREMENT PRIMARY KEY,
cate_name varchar(128) NOT NULL UNIQUE
)
CREATE TABLE product
(
pid int AUTO_INCREMENT
PRIMARY KEY,
name varchar(128) NOT NULL,
price decimal NOT NULL,
cate_id int null,
CONSTRAINT name UNIQUE (name),
CONSTRAINT fk_product_cateid FOREIGN KEY (cate_id) REFERENCES category (cate_id)
);
Mapper接口
public interface CateMapper {
int insert(@Param("cate") Category category);
}
public interface ProductMapper {
int insert(@Param("product") Product product);
}
Mapper.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smart.ssm.mapper.CateMapper">
<resultMap id="BaseResultMaper" type="Category">
<id column="cate_id" property="cateId"/>
<result column="cate_name" property="cateName"/>
</resultMap>
<insert id="insert" keyProperty="cate.cateId" useGeneratedKeys="true">
INSERT INTO category(cate_name)
VALUES (#{cate.cateName})
</insert>
</mapper>
<?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.smart.ssm.mapper.ProductMapper">
<resultMap id="BaseResultMap" type="com.smart.ssm.entity.Product">
<id column="pid" jdbcType="INTEGER" property="pid"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="price" jdbcType="DECIMAL" property="price"/>
<result property="cateId" column="cate_id"/>
</resultMap>
<insert id="insert">
INSERT INTO product(name, price, cate_id)
VALUES (#{product.name}, #{product.price}, #{product.cateId})
</insert>
</mapper>
Service层
@Service
public class IndexServiceImpl implements IndexService {
@Resource
CateMapper cateMapper;
@Resource
ProductMapper productMapper;
/**
* @param category
* @return
*/
@Override
public int saveCate(Category category) {
int insert = cateMapper.insert(category);
List<Product> products = category.getProducts();
for (Product product : products) {
// 设置关联的外键字段的值 脏数据
product.setCateId(category.getCateId());
productMapper.insert(product);
}
return insert;
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-mybatis.xml"})
public class IndexServiceImplTest {
@Resource
IndexService indexService;
@Test
public void saveCate() {
Category category = new Category();
category.setCateName("电脑");
List<Product> productList = new ArrayList<>();
category.setProducts(productList);
for (int i = 0; i < 10; i++) {
Product product = new Product();
product.setCateId(category.getCateId());
product.setPrice(new BigDecimal("999.00"));
product.setName("test电脑" + i);
productList.add(product);
}
indexService.saveCate(category);
}
}
级联查询
多表查询
核心点 : 子元素collection
一次性查询所有的数据保存子表的数据
mapper接口
public interface CateMapper {
List<Category> selectAll();
}
mapper.xml
主表
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smart.ssm.mapper.CateMapper">
<resultMap id="BaseResultMap" type="Category">
<id column="cate_id" property="cateId"/>
<result column="cate_name" property="cateName"/>
</resultMap>
<resultMap id="collectionResultMap" type="Category" extends="BaseResultMap">
<!-- 一对一 以及多对多-->
<collection property="products" resultMap="com.smart.ssm.mapper.ProductMapper.BaseResultMap"/>
</resultMap>
<select id="selectAll" resultMap="collectionResultMap">
SELECT *
FROM category c
LEFT JOIN product p ON c.cate_id = p.cate_id
</select>
</mapper>
<?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.smart.ssm.mapper.ProductMapper">
<resultMap id="BaseResultMap" type="com.smart.ssm.entity.Product">
<id column="pid" jdbcType="INTEGER" property="pid"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="price" jdbcType="DECIMAL" property="price"/>
<result property="cateId" column="cate_id"/>
</resultMap>
</mapper>
Service层
@Service
public class IndexServiceImpl implements IndexService {
@Resource
CateMapper cateMapper;
public List<Category> getCategoryData() {
List<Category> categories = cateMapper.selectAll();
return categories;
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-mybatis.xml"})
public class IndexServiceImplTest {
@Resource
IndexService indexService;
@Test
public void getCategoryData() {
List<Category> categoryData = indexService.getCategoryData();
System.out.println(categoryData);
}
}
注意事项:
性能问题: 一定要注意关联的子数据不能太多
级联修改
在开发中,一般只需要修改主表的状态字段
多对多
开发中能不用就不要使用多对多,因为性能很差
注意: 凡是建立多对多的关系需要第三张表
角色表--- 权限表
语法格式
select *
from 表1 left join 第三张表 on 条件 left join 表2 on 条件
关系模型
role(角色表)
CREATE TABLE role
(
role_id int AUTO_INCREMENT PRIMARY KEY,
role_name varchar(64) NOT NULL UNIQUE COMMENT 'admin user guest'
)
权限表
CREATE TABLE privilege
(
privilege_id int AUTO_INCREMENT PRIMARY KEY,
name varchar(64) COMMENT '增 删 改 差'
)
第三种表
- 关联权限表的主键
- 关联角色表的主键
CREATE TABLE t_role_privilege
(
id int AUTO_INCREMENT PRIMARY KEY,
privilege_id int NOT NULL REFERENCES privilege (privilege_id),
role_id int NOT NULL REFERENCES role (role_id)
)
对象模型
@Data
public class Privilege {
private Integer privilegeId;
private String privilegeName;
private List<Role> roleList;
}
@Data
public class Role {
private Integer roleId;
private String roleName;
private List<Privilege> privilegeList;
}
Mapper.xml
权限
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smart.ssm.mapper.PrivilegeMapper">
<resultMap id="BaseResultMap" type="Privilege">
<id property="privilegeId" column="privilege_id"/>
<result property="privilegeName" column="name"/>
</resultMap>
<resultMap id="collectionResultMap" type="Privilege" extends="BaseResultMap">
<collection property="roleList" resultMap="com.smart.ssm.mapper.RoleMapper.BaseResultMap"/>
</resultMap>
<select id="selectById" resultMap="collectionResultMap">
SELECT *
FROM privilege p
LEFT JOIN t_role_privilege trp ON p.privilege_id = trp.privilege_id
LEFT JOIN role r ON r.role_id = trp.role_id
WHERE p.privilege_id = #{pid}
</select>
</mapper>
角色
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smart.ssm.mapper.RoleMapper">
<resultMap id="BaseResultMap" type="Role">
<id property="roleId" column="role_id"/>
<result property="roleName" column="role_name"/>
</resultMap>
<select id="selectById" resultType="com.smart.ssm.entity.Role">
</select>
</mapper>
Mapper接口
权限
public interface PrivilegeMapper {
Privilege selectById(@Param("pid") int pid);
}
角色
Service层
@Service
public class AccountServiceImpl implements AccountService {
@Resource
PrivilegeMapper privilegeMapper;
@Override
public Privilege findById(int pid) {
Privilege privilege = privilegeMapper.selectById(pid);
return privilege;
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-mybatis.xml"})
public class AccountServiceTest {
@Resource
AccountService accountService;
@Test
public void findById() {
Privilege privilege = accountService.findById(2);
System.out.println(privilege.getPrivilegeName());
System.out.println(privilege.getRoleList());
}
}