几天前我整理了一下Mybatis常用语句,主要包含增删查改的基本语法,这次我们继续介绍Mybatis一对一,一对多以及多对多的用法。
首先是添加db.properties,sqlMapConfig.xml以及log4j.properties文件,并添加mybatis、log4j、mysql的jar包,代码和上一期博客一样,这里不再成功重复。
然后我们新增实体类,这次我们把一对一以及一对多关系的实体对象也添加进去,其中User代码如下:
package cn.neu.mybatis.entity;
import java.util.Date;
import java.util.List;
public class User {
private int uId;
private String uName;
private String uPwd;
private String uPhone;
private double uBalance;
private int uState;
private int uRole;
private String uImage;//用户头像
private Date uBirth;
//一对多关系映射
private List orders;
public int getuId() {
return uId;
}
public void setuId(int uId) {
this.uId = uId;
}
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getuPwd() {
return uPwd;
}
public void setuPwd(String uPwd) {
this.uPwd = uPwd;
}
public String getuPhone() {
return uPhone;
}
public void setuPhone(String uPhone) {
this.uPhone = uPhone;
}
public double getuBalance() {
return uBalance;
}
public void setuBalance(double uBalance) {
this.uBalance = uBalance;
}
public int getuState() {
return uState;
}
public void setuState(int uState) {
this.uState = uState;
}
public int getuRole() {
return uRole;
}
public void setuRole(int uRole) {
this.uRole = uRole;
}
public String getuImage() {
return uImage;
}
public void setuImage(String uImage) {
this.uImage = uImage;
}
public Date getuBirth() {
return uBirth;
}
public void setuBirth(Date uBirth) {
this.uBirth = uBirth;
}
public List getOrders() {
return orders;
}
public void setOrders(List orders) {
this.orders = orders;
}
public User(int uId, String uName, String uPwd, String uPhone, double uBalance, int uState, int uRole,String uImage,Date uBirth) {
super();
this.uId = uId;
this.uName = uName;
this.uPwd = uPwd;
this.uPhone = uPhone;
this.uBalance = uBalance;
this.uState = uState;
this.uRole = uRole;
this.uImage = uImage;
this.uBirth = uBirth;
}
public User() {
super();
}
public User(String uName, String uPwd, String uPhone) {
super();
this.uName = uName;
this.uPwd = uPwd;
this.uPhone = uPhone;
}
//添加注册信息
public User(String uName, String uPwd, String uPhone, Date uBirth) {
super();
this.uName = uName;
this.uPwd = uPwd;
this.uPhone = uPhone;
this.uBirth = uBirth;
}
public User(String uName, String uPwd, String uPhone, String uImage) {
super();
this.uName = uName;
this.uPwd = uPwd;
this.uPhone = uPhone;
this.uImage = uImage;
}
public User(String uName, String uPwd) {
super();
this.uName = uName;
this.uPwd = uPwd;
}
@Override
public String toString() {
return "User [uId=" + uId + ", uName=" + uName + ", uPwd=" + uPwd + ", uPhone=" + uPhone + ", uBalance="
+ uBalance + ", uState=" + uState + ", uRole=" + uRole + ", uImage=" + uImage + ", uBirth=" + uBirth
+ "]";
}
}
User类与Orders类是一对多的关系,所以用List表示,Orders类代码如下:
package cn.neu.mybatis.entity;
import java.sql.Timestamp;
import java.util.List;
public class Orders {
private int oId;
private int oUId;
private Timestamp oTime;
private double oSumSale;
//一个订单可能包含多个购买的商品,这个时候需要进行一对多映射,
//使用List注入
private List orderDetails;
//一个订单只能有一个用户
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List getOrderDetails() {
return orderDetails;
}
public void setOrderDetails(List orderDetails) {
this.orderDetails = orderDetails;
}
public Orders() {
super();
}
public Orders(int oId, int oUId, Timestamp oTime, double oSumSale) {
super();
this.oId = oId;
this.oUId = oUId;
this.oTime = oTime;
this.oSumSale = oSumSale;
}
public Orders(int oUId, double oSumSale) {
super();
this.oId = (int)(Math.random()*123456);
this.oUId = oUId;
this.oTime = new Timestamp(System.currentTimeMillis());
this.oSumSale = oSumSale;
}
public int getoId() {
return oId;
}
public void setoId(int oId) {
this.oId = oId;
}
public int getoUId() {
return oUId;
}
public void setoUId(int oUId) {
this.oUId = oUId;
}
public Timestamp getoTime() {
return oTime;
}
public void setoTime(Timestamp oTime) {
this.oTime = oTime;
}
public double getoSumSale() {
return oSumSale;
}
public void setoSumSale(double oSumSale) {
this.oSumSale = oSumSale;
}
@Override
public String toString() {
return "Orders [oId=" + oId + ", oUId=" + oUId + ", oTime=" + oTime + ", oSumSale=" + oSumSale + "]";
}
}
一个订单类可能包含多条订单详情信息,但一个订单只能属于一个用户,接下来是订单详情类OrderDetail,其代码如下:
package cn.neu.mybatis.entity;
public class OrderDetail {
private int oDId;
private int oDOId;
private int oDGId;
private int oDCount;
//一个条目对应一个商品 一对一
private Goods goods;
public OrderDetail() {
super();
}
public OrderDetail(int oDId, int oDOId, int oDGId, int oDCount) {
super();
this.oDId = oDId;
this.oDOId = oDOId;
this.oDGId = oDGId;
this.oDCount = oDCount;
}
public OrderDetail(int oDOId, int oDGId, int oDCount) {
super();
this.oDOId = oDOId;
this.oDGId = oDGId;
this.oDCount = oDCount;
}
public int getoDId() {
return oDId;
}
public void setoDId(int oDId) {
this.oDId = oDId;
}
public int getoDOId() {
return oDOId;
}
public void setoDOId(int oDOId) {
this.oDOId = oDOId;
}
public int getoDGId() {
return oDGId;
}
public void setoDGId(int oDGId) {
this.oDGId = oDGId;
}
public int getoDCount() {
return oDCount;
}
public void setoDCount(int oDCount) {
this.oDCount = oDCount;
}
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
@Override
public String toString() {
return "OrderDetail [oDId=" + oDId + ", oDOId=" + oDOId + ", oDGId=" + oDGId + ", oDCount=" + oDCount + "]";
}
}
一条订单详情信息对应一个商品,这里是一对一的关系,接下来是商品Goods类,其代码如下:
package cn.neu.mybatis.entity;
import java.sql.Timestamp;
public class Goods {
private int gId;
private String gName;
private double gSale;
private int gCount;
private String gType;
private String gDesc;
private Timestamp gTime;
public Goods(int gId, String gName, double gSale, int gCount, String gType, String gDesc, Timestamp gTime) {
super();
this.gId = gId;
this.gName = gName;
this.gSale = gSale;
this.gCount = gCount;
this.gType = gType;
this.gDesc = gDesc;
this.gTime = gTime;
}
public Timestamp getgTime() {
return gTime;
}
public void setgTime(Timestamp gTime) {
this.gTime = gTime;
}
public Goods() {
super();
}
public Goods(int gId, String gName, double gSale, int gCount, String gType, String gDesc) {
super();
this.gId = gId;
this.gName = gName;
this.gSale = gSale;
this.gCount = gCount;
this.gType = gType;
this.gDesc = gDesc;
}
public int getgId() {
return gId;
}
public void setgId(int gId) {
this.gId = gId;
}
public String getgName() {
return gName;
}
public void setgName(String gName) {
this.gName = gName;
}
public double getgSale() {
return gSale;
}
public void setgSale(double gSale) {
this.gSale = gSale;
}
public int getgCount() {
return gCount;
}
public void setgCount(int gCount) {
this.gCount = gCount;
}
public String getgType() {
return gType;
}
public void setgType(String gType) {
this.gType = gType;
}
public String getgDesc() {
return gDesc;
}
public void setgDesc(String gDesc) {
this.gDesc = gDesc;
}
@Override
public String toString() {
return "Goods [gId=" + gId + ", gName=" + gName + ", gSale=" + gSale + ", gCount=" + gCount + ", gType=" + gType
+ ", gDesc=" + gDesc + ", gTime=" + gTime + "]";
}
}
这里我们再添加一个实体类OrdersCustom,该类继承Orders类,并另外添加两个属性,其代码如下:
package cn.neu.mybatis.entity;
public class OrdersCustom extends Orders {
private String uName;
private String uPhone;
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getuPhone() {
return uPhone;
}
public void setuPhone(String uPhone) {
this.uPhone = uPhone;
}
public OrdersCustom() {
super();
}
public OrdersCustom(String uName, String uPhone) {
super();
this.uName = uName;
this.uPhone = uPhone;
}
@Override
public String toString() {
return "OrdersCustom [uName=" + uName + ", uPhone=" + uPhone + "]";
}
}
实体类创建好了之后,接下来是mapper层,我们新建OrdersMapper接口,里面包含的方法如下:
package cn.neu.mybatis.mapper;
import java.util.List;
import cn.neu.mybatis.entity.Orders;
import cn.neu.mybatis.entity.OrdersCustom;
import cn.neu.mybatis.entity.User;
public interface OrdersMapper {
public List findOrderUserResultMap() throws Exception;
public List findOrderUserResultType() throws Exception;
public List findOrderDetailsResultMap() throws Exception;
public List findUsersAndGoods() throws Exception;
}
然后我们创建对应的OrdersMapper.xml文件,其代码如下:
上述xml文件主要包含了一对一,一对多以及多对多关系的映射,我们一一进行讲解:
(1)第一个方法findOrderUserResultMap,首先通过association关联User类(一对一,使用javaType),通过resultMap把想要查询的信息放进去,然后写SQL语句关联用户的编号即可;
(2)第二个方法findOrderUserResultType,我们不把查询的信息放进resultMap中,而是用resultType指向具体的类——OrdersCustom,但是这样的话SQL语句查询的属性必须进行别名映射,这是与第一个方法中SQL语句的不同之处;
(3)第三个方法findOrderDetailsResultMap,返回值是List
(4)第四个方法findUsersAndGoods,返回值是List
接下来我们进行单元测试,新建OrdersMapperTest,其代码如下:
package cn.neu.mybatis.test;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.neu.mybatis.entity.OrderDetail;
import cn.neu.mybatis.entity.Orders;
import cn.neu.mybatis.entity.OrdersCustom;
import cn.neu.mybatis.entity.User;
import cn.neu.mybatis.mapper.OrdersMapper;
public class OrdersMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrderUserResultMap() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List orders = ordersMapper.findOrderUserResultMap();
for(Orders o : orders) {
System.out.println(o.toString());
System.out.println(o.getUser().toString());
System.out.println("----------------------");
}
session.close();
}
/**
* 订单与用户信息关联
* @throws Exception
*/
@Test
public void testFindOrderUserResultType() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List orders = ordersMapper.findOrderUserResultType();
for(OrdersCustom o:orders){
System.out.println(o.toString());
System.out.println(o.getoId()+":"+o.getoTime());
System.out.println("------------------------");
}
session.close();
}
@Test
public void testFindOrderDetailsResultMap() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List orders = ordersMapper.findOrderDetailsResultMap();
for(Orders o:orders){
System.out.println("用户名:"+o.getUser().getuName());
System.out.println("订单号:"+o.getoId());
System.out.println("该订单详情:");
for(OrderDetail od:o.getOrderDetails()){
System.out.println("商品号:"+od.getoDGId()+",购买数量:"+od.getoDCount());
}
System.out.println("-----------------------------------");
}
}
@Test
public void testFindUsersAndGoods() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List users = ordersMapper.findUsersAndGoods();
for(User u:users){
System.out.println("用户名:"+u.getuName()+",手机号:"+u.getuPhone());
System.out.println("------------------------------");
for(Orders o:u.getOrders()){
System.out.println("订单编号:"+o.getoId());
System.out.println("订单详情:");
for(OrderDetail od:o.getOrderDetails()){
System.out.println("商品名:"+od.getGoods().getgName()+
",购买数量:"+od.getoDCount()
+",单价:"+od.getGoods().getgSale());
}
}
}
}
}
大家可以自己去运行测试一下,这里我就不截图了。
好了,本期Mybatis的常见关联用法就到这里了,以后如果有其他的会进行补充,我们下期再见!