Mybatis實現–多對多數據庫關係
多對多關係在數據庫中十分常見,比如一個購物系統中,一個用戶可以有多個訂單,這個是一對多的關係;一個訂單可以有多個商品,一個商品又可以存在於多個訂單,這就是多對多的關係。對於數據庫中多對多的關係建議使用一個中間表來維護關係,中間表中的訂單id作爲外鍵參照訂單表的id,商品id作爲外鍵參照商品表的id
建表造數據
- TB_USERS ( 用戶表 )
- TB_ARTICLE (商品表)
- TB_ORDER (訂單表)
- TB_ITEM (中間表)
TB_USERS
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_users
-- ----------------------------
DROP TABLE IF EXISTS `tb_users`;
CREATE TABLE `tb_users` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`USERNAME` varchar(18) DEFAULT NULL,
`LOGINNAME` varchar(18) DEFAULT NULL,
`PASSWORD` varchar(18) DEFAULT NULL,
`PHONE` varchar(18) DEFAULT NULL,
`ADDRESS` varchar(18) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_users
-- ----------------------------
INSERT INTO `tb_users` VALUES ('1', '傑克', 'jack', '123456', '13765435673', '廣州');
INSERT INTO `tb_users` VALUES ('2', '瑪麗', 'mary', '123456', '13765435673', '北京');
TB_ORDER
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`CODE` varchar(32) DEFAULT NULL,
`TOTAL` double DEFAULT NULL,
`USER_ID` int(11) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `USER_ID` (`USER_ID`),
CONSTRAINT `USER_ID` FOREIGN KEY (`USER_ID`) REFERENCES `tb_users` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES ('1', '546457657658ygyufyu', '566', '1');
INSERT INTO `tb_order` VALUES ('2', '3534terteyeyew', '467', '1');
TB_ARTICLE
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_article
-- ----------------------------
DROP TABLE IF EXISTS `tb_article`;
CREATE TABLE `tb_article` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`NAME` varchar(18) DEFAULT NULL,
`PRICE` double(10,2) DEFAULT NULL,
`REMARK` varchar(18) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_article
-- ----------------------------
INSERT INTO `tb_article` VALUES ('1', '瘋狂java講義', '11.00', '瘋狂java講義');
INSERT INTO `tb_article` VALUES ('2', '瘋狂android講義', '22.00', '瘋狂android講義');
INSERT INTO `tb_article` VALUES ('3', '瘋狂ios講義', '33.00', '瘋狂ios講義');
INSERT INTO `tb_article` VALUES ('4', 'spring企業級開發', '44.00', 'spring企業級開發');
TB_ITEM
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_item
-- ----------------------------
DROP TABLE IF EXISTS `tb_item`;
CREATE TABLE `tb_item` (
`ORDER_ID` int(11) NOT NULL,
`ARTICLE_ID` int(11) NOT NULL,
`AMOUNT` int(11) DEFAULT NULL,
PRIMARY KEY (`ORDER_ID`,`ARTICLE_ID`),
KEY `ARTICLE_ID` (`ARTICLE_ID`),
CONSTRAINT `ORDER_ID` FOREIGN KEY (`ORDER_ID`) REFERENCES `tb_order` (`ID`),
CONSTRAINT `ARTICLE_ID` FOREIGN KEY (`ARTICLE_ID`) REFERENCES `tb_article` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_item
-- ----------------------------
INSERT INTO `tb_item` VALUES ('1', '1', '1');
INSERT INTO `tb_item` VALUES ('1', '2', '1');
INSERT INTO `tb_item` VALUES ('1', '3', '2');
INSERT INTO `tb_item` VALUES ('2', '1', '1');
INSERT INTO `tb_item` VALUES ('2', '4', '2');
創建與數據庫表對應的實體類
- User.java
- Order.java
- Article.java
User.java
public class User implements Serializable{
private Integer id;
private String username;
private String loginname;
private String password;
private String phone;
private String address;
//用戶和訂單是一對多的關係
private List<Order> orders;
//set get方法省略
}
Order.java
public class Order implements Serializable{
private Integer id;
private String code;
private Double total;
//訂單和用戶是多對一的關係
private User user;
//訂單和商品是多對多的關係
private List<Article> articles;
//set get方法省略
}
Article.java
public class Article {
private Integer id;
private String name;
private Double price;
private String remark;
//商品和訂單應該是多對多的關係
private List<Order> orders;
}
創建mapper映射xml文件
- UserMapper.xml
- OrderMapper.xml
- ArticleMapper.xml
UserMapper.xml
selectById
根據用戶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="com.liusl.mapper.UserMapper">
<select id="selectById" resultMap="userResultMap">
SELECT * FROM TB_USERS WHERE ID = #{id}
</select>
<resultMap id="userResultMap" type="User">
<id property="id" column="ID" />
<result property="username" column="USERNAME" />
<result property="loginname" column="LOGINNAME" />
<result property="password" column="PASSWORD" />
<result property="phone" column="PHONE" />
<result property="address" column="ADDRESS" />
<!--用戶和訂單是一對多的關係使用collection標籤-->
<collection property="orders" javaType="ArrayList" column="id" fetchType="lazy" ofType="com.liusl.model.Order" select="com.liusl.mapper.OrderMapper.selectByUserId">
<id property="id" column="ID" />
<result property="code" column="CODE" />
<result property="total" column="TOTAL" />
</collection>
</resultMap>
</mapper>
因爲查詢用戶的時候會查詢該用戶所有訂單的詳情,用戶與訂單是一對多的關係,使用collection標籤;collection標籤中有幾個屬性。
- property:對應的是User.java中的屬性名稱“orders”
- column: 列名id,傳給select屬性中方法的參數
- fetchType:數據加載方式,lazy代表懶加載,查詢的時候可能不會訪問訂單信息,啓用lazy還需要配置
mybatis:
configuration:
lazy-loading-enabled: true
aggressive-lazy-loading: false
- ofType: select返回的數據類型
- select:調用其他的方法來返回該collection的結果,在這個地方會調用com.liusl.mapper.OrderMapper.selectByUserId
OrderMapper.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.liusl.mapper.OrderMapper">
<!--根據Order Id查詢訂單信息-->
<select id="selectByOrderId" resultMap="orderResultMap">
SELECT u.*,o.ID AS OID,o.CODE,o.TOTAL
FROM TB_USERS u,TB_ORDER o
WHERE u.ID = o.USER_ID AND o.ID = #{id}
</select>
<!--根據用戶ID 查詢訂單信息-->
<select id="selectByUserId" resultType="com.liusl.model.Order">
SELECT * FROM TB_ORDER WHERE USER_ID = #{id}
</select>
<resultMap id="orderResultMap" type="Order">
<id property="id" column="ID" />
<result property="code" column="CODE" />
<result property="total" column="TOTAL" />
<!--多對一關聯,多個訂單有一個用戶-->
<association property="user2" javaType="User2">
<id property="id" column="ID" />
<result property="username" column="USERNAME" />
<result property="loginname" column="LOGINNAME" />
<result property="password" column="PASSWORD" />
<result property="phone" column="PHONE" />
<result property="address" column="ADDRESS" />
</association>
<!--多對多關聯collection-->
<collection property="articles" javaType="ArrayList" ofType="com.liusl.model.Article" fetchType="lazy" column="OID" select="com.liusl.mapper.ArticleMapper.selectArticleByOrderId">
<id property="id" column="ID" />
<result property="name" column="NAME" />
<result property="price" column="PRICE" />
<result property="remark" column="REMARK" />
</collection>
</resultMap>
</mapper>
ArticleMapper.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.liusl.mapper.ArticleMapper">
<!--根據Order Id查詢商品信息-->
<!--傳過來的值是ORDER_ID,首先通過中間表查詢出該OID中的所有商品ID,在通過ARTICLE表查詢出商品信息-->
<select id="selectArticleByOrderId" resultType="com.liusl.model.Article">
SELECT *
FROM TB_ARTICLE
WHERE id IN (
SELECT ARTICLE_ID FROM TB_ITEM WHERE ORDER_ID = #{id}
)
</select>
</mapper>
創建mapper.java文件
- UserMapper.java
- OrderMapper.java
UserMapper.java
@Mapper
public interface UserMapper {
public User selectById(Integer id);
}
OrderMapper.java
@Mapper
public interface OrderMapper {
public Order selectByOrderId(Integer id);
}
測試
創建測試類
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
@Test
public void selectById() throws Exception {
User user = userMapper.selectById(1);
System.out.println(JSON.toJSONString(user,true));
}
@Test
public void selectByOrderId() throws Exception{
Order order = orderMapper.selectByOrderId(1);
System.out.println(JSON.toJSONString(order,true));
}
}
返回結果分別是:
{
"address":"廣州",
"id":1,
"loginname":"jack",
"orders":[
{
"code":"546457657658ygyufyu",
"id":1,
"total":566.0
},
{
"code":"3534terteyeyew",
"id":2,
"total":467.0
}
],
"password":"123456",
"phone":"13765435673",
"username":"傑克"
}
{
"articles":[
{
"id":1,
"name":"瘋狂java講義",
"price":11.0,
"remark":"瘋狂java講義"
},
{
"id":2,
"name":"瘋狂android講義",
"price":22.0,
"remark":"瘋狂android講義"
},
{
"id":3,
"name":"瘋狂ios講義",
"price":33.0,
"remark":"瘋狂ios講義"
}
],
"code":"546457657658ygyufyu",
"id":1,
"total":566.0,
"user2":{
"address":"廣州",
"id":1,
"loginname":"jack",
"password":"123456",
"phone":"13765435673",
"username":"傑克"
}
}