1. 程式人生 > >一對一查詢

一對一查詢

zf2 bcg gwt cond nts rgw ima cxf bom

需求:

查詢訂單信息,關聯查詢創建訂單的用戶信息。

記住:用Mybatis開發的順序就是

1.寫sql語句

2.創建pojo類來完成映射

3.寫Mapper.xml

4.寫Mapper.java接口

---------------------------------------------------------------------------------------------------------------------------------------------------

我們知道Mybatis中mapper.xml中分為resultType和resultMap兩種,這兩種我們都講:

一:先講resultMap:

先給出案例結構:

技術分享

cn.itcast.mybatis.po包下面的類(items,orderdetail,Orders,User)都是根據數據庫的4張表創建的實體類。

1.我們先來分析一下怎麽寫sql語句:

寫sql語句時要先根據需求確定查詢的主表和查詢的關聯表:

根據“查詢訂單信息,關聯查詢創建訂單的用戶信息” 很明顯,查詢的主表是訂單表,查詢的關聯是用戶表。

關聯查詢使用內鏈接?還是外鏈接?由於orders表中有一個外鍵(user_id),通過外鍵關聯查詢用戶表只能查詢出一條記錄,可以使用內鏈接。

sql如下:

SELECT

orders.*,

USER.username,

USER.sex,

USER.address

FROM

orders,

USER

WHERE orders.user_id = user.id

2.根據select(orders.*,USER.username,USER.sex,USER.address)語句 創建Pojo類

我們創建的pojo類要滿足orders.*,USER.username,USER.sex,USER.address這些映射,很明顯單純依靠數據庫的映射(Orders.java和User.java)不能滿足,所以要新寫一個類OrdersCustom.java。

如下:

技術分享
package cn.itcast.mybatis.po;

import java.util.Date;

public class OrdersCustom  extends Orders{
    private String username;
    private String sex;
    private String address;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    

}
技術分享

為什麽這個類要繼承Orders而不是繼承User.java因為根據orders.*,USER.username,USER.sex,USER.address,很明顯,要映射的數據是order表中的全部數據以及user

表中的username,sex,address這些數據,直接繼承Order類的話就可以少定義一些屬性,只要定義username,sex,address。就可以了。

3.寫Mapper.xml和Mapper.java接口(放在同一個包下面,用接口的方式去加載)

技術分享

OrderMapperCustom.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">
<!-- nanmespace:命名空間。 作用就是對sql進行分類話管理,理解Sal分離

註意:使用mapper代理方式,namespace有特殊重要的作用
-->

<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom">
   

        <select id="findOrdersUser"  resultType="cn.itcast.mybatis.po.OrdersCustom">
        SELECT ORDERS.* , 
        user.`username`,
        user.`sex`,
        user.`address` 
        FROM orderS,USER
         WHERE ORDERS.`user_id`=USER.`id`

    
    </select>
    
   
</mapper>
技術分享

OrdersMapperCustom.java代碼如下:

技術分享
package cn.itcast.mybatis.mapper;

import java.util.List;

import cn.itcast.mybatis.po.OrdersCustom;

public interface OrdersMapperCustom {
    public List<OrdersCustom> findOrdersUser();

}
技術分享

同時不要忘了在SqlMapConfig.xml。

技術分享
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    
      
    
    <!-- properties的配置必須寫在typeAliases的上面 -->
    <properties resource="db.properties"></properties>


 
       
 <!-- 和spring整合後 environments配置將廢除-->
    <environments default="development">
        <environment id="development">
        <!-- 使用jdbc事務管理-->
            <transactionManager type="JDBC" />
        <!-- 數據庫連接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>

    
        <mappers>
            
           <!--  用mapper接口的方式加載-->
           <!-- 
           遵循一些規範:需要將mapper接口類名和mapper.xml映射文件名稱保持一致
           且在一個目錄中。
           當著這個規範的前提是:使用mapper代理方法。
           
           
           
            -->
            <mapper class="cn.itcast.mybatis.mapper.OrdersMapperCustom"/>
            
            
         </mappers>
    
    
    
</configuration>
技術分享

4.編寫測試代碼Mybatis_mappertest.java:

技術分享
package cn.itcast.mybatis.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
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.itcast.mybatis.mapper.OrdersMapperCustom;
import cn.itcast.mybatis.mapper.userMapper;
import cn.itcast.mybatis.po.User;
import cn.itcast.mybatis.po.UserCustom;
import cn.itcast.mybatis.po.UserQueryVo;

public class Mybatis_mappertest {
    
    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void setup() throws IOException
    {   String resource="SqlMapConfig.xml";
        InputStream inputStream= Resources.getResourceAsStream(resource);
        //主要是生成SqlsessionFactory。
        this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testMaper()
    {
        SqlSession sqlSession=null;
        
        sqlSession=sqlSessionFactory.openSession();
        //生成代理類
        OrdersMapperCustom orderMapper=sqlSession.getMapper(OrdersMapperCustom.class);

        orderMapper.findOrdersUser();
       
        
        
    }

}
技術分享

運行結果:一切正常。

二:再講resultMap(重點):

resultMap映射的思想:

使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關聯查詢出來的用戶信息映射到orders對象中的user屬性中。也就是說查出來的user信息都要映射在orders中新開的一個user屬性中。

還是按照第一sql語句,第二pojo類,第三mapper.xml,mapper.java接口這種順序來寫。

1.sql語句:和之前的resulrType的sql語句一樣:

SELECT

orders.*,

USER.username,

USER.sex,

USER.address

FROM

orders,

USER

WHERE orders.user_id = user.id

2.寫pojo類:在原來的Orders.java中新增一個User屬性:

User類:

技術分享
package cn.itcast.mybatis.po;

import java.util.Date;
//對應數據庫中的user表
public class User {
private int id;//對應數據庫中主鍵
private String username;//對應數據庫中用戶的名稱
private Date birthday;//對應數據庫中的生日
private String sex;//性別
private String address;//地址
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getUsername() {
    return username;
}
public void setUsername(String username) {
    this.username = username;
}
public Date getBirthday() {
    return birthday;
}
public void setBirthday(Date birthday) {
    this.birthday = birthday;
}
public String getSex() {
    return sex;
}
public void setSex(String sex) {
    this.sex = sex;
}
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}

}
技術分享

Orders.java類:

技術分享
package cn.itcast.mybatis.po;

import java.util.Date;

public class Orders {
private Integer id;
private Integer user_id;
private String number;
private Date createtime;
private String note;
//新增了一個User屬性,為了保存查詢得到的關聯的User表的信息
private User user;
public User getUser() {
    return user;
}
public void setUser(User user) {
    this.user = user;
}
public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}
public Integer getUser_id() {
    return user_id;
}
public void setUser_id(Integer user_id) {
    this.user_id = user_id;
}
public String getNumber() {
    return number;
}
public void setNumber(String number) {
    this.number = number;
}
public Date getCreatetime() {
    return createtime;
}
public void setCreatetime(Date createtime) {
    this.createtime = createtime;
}
public String getNote() {
    return note;
}
public void setNote(String note) {
    this.note = note;
}


}
技術分享

3.寫mapper.xml和mapper.java接口

OrdersMapperCustom.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">
<!-- nanmespace:命名空間。 作用就是對sql進行分類話管理,理解Sal分離

註意:使用mapper代理方式,namespace有特殊重要的作用
-->

<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom">
  
        <!-- 配置映射的訂單信息 -->
        <!-- id:指定查詢列中的唯 一標識,訂單信息的中的唯 一標識,如果有多個列組成唯一標識,配置多個id
          就是說id要能唯一的標識出數據庫中的Order表。
            column:訂單信息的唯 一標識 列
            property:訂單信息的唯 一標識 列所映射到Orders中哪個屬性
            
          -->
    
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
   <!-- 這一行的作用是要能唯一的識別出order表的,那麽很明顯是主鍵id -->
    <id column="id" property="id"/>
    
    <!-- 以下的幾行result column就是表中的字段   property就是對應到相應pojo類中的屬性-->
    <result column="user_id" property="user_id"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note"  property="note"/>
    
    
    
        <!-- 配置映射的關聯的用戶信息 -->
        <!-- association:用於映射關聯查詢單個對象的信息
        property:要將關聯查詢的用戶信息映射到Orders中哪個屬性
         -->
    <!-- 下面的代碼比較特殊,因為Order表是直接關聯到user表,下面這麽寫的目的是把user表映射到Order類中
     <association property="user"這裏的user指的是orders類中的user,對應的是cn.itcast.mybatis.po.User
     
    
     -->
    <association property="user" javaType="cn.itcast.mybatis.po.User">
       <!-- 
       <id column="user_id" property="id"/>這裏的是user_id指的是order表中只有這個屬性能表示唯一的user表
        -->
        <id column="user_id" property="id"/>
        
        <!-- 接下來的result  property什麽的都是為了把user表中的字段能匹配到 
        cn.itcast.mybatis.po.User這個類的屬性中
        -->
           <result column="username" property="username"/>
          <result column="sex" property="sex"/>
          <result column="address" property="address"/>
        </association>
    
</resultMap>
    
    
        <select id="findOrdersUser"  resultType="cn.itcast.mybatis.po.OrdersCustom">
        SELECT ORDERS.* , 
        user.`username`,
        user.`sex`,
        user.`address` 
        FROM orderS,USER
         WHERE ORDERS.`user_id`=USER.`id`

    
    </select>
    
      <select id="findOrdersUseResultMap"  resultMap="OrdersUserResultMap">
        SELECT ORDERS.* , 
        user.`username`,
        user.`sex`,
        user.`address` 
        FROM orderS,USER
         WHERE ORDERS.`user_id`=USER.`id`

    
    </select>
</mapper>
技術分享

OrdersMapperCustom.java接口

技術分享
package cn.itcast.mybatis.mapper;

import java.util.List;

import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.OrdersCustom;

public interface OrdersMapperCustom {
//這裏的的函數名字要和OrdersMapperCustom.xml中的id一模一樣
    public List<OrdersCustom> findOrdersUser();
    public List<Orders> findOrdersUseResultMap();

}
技術分享

Junit測試代碼:

技術分享
package cn.itcast.mybatis.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
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.itcast.mybatis.mapper.OrdersMapperCustom;
import cn.itcast.mybatis.mapper.userMapper;
import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.User;
import cn.itcast.mybatis.po.UserCustom;
import cn.itcast.mybatis.po.UserQueryVo;

public class Mybatis_mappertest {
    
    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void setup() throws IOException
    {   String resource="SqlMapConfig.xml";
        InputStream inputStream= Resources.getResourceAsStream(resource);
        //主要是生成SqlsessionFactory。
        this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testMaper()
    {
        SqlSession sqlSession=null;
        
        sqlSession=sqlSessionFactory.openSession();
        //生成代理類
        OrdersMapperCustom orderMapper=sqlSession.getMapper(OrdersMapperCustom.class);
    //創建包裝對象,設置查詢條件
        //orderMapper.findOrdersUser();
        
       @SuppressWarnings("unused")
    List<Orders>list=orderMapper.findOrdersUseResultMap();
        
        
    }

}
技術分享

運行結果:一切正常。

resultType和resultMap實現一對一查詢小結

實現一對一查詢:

resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。

如果沒有查詢結果的特殊要求建議使用resultType。

resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。

resultMap可以實現延遲加載,resultType無法實現延遲加載。

一對一查詢