1. 程式人生 > >MyBatis一對一、一對多、多對多級聯查詢

MyBatis一對一、一對多、多對多級聯查詢

0.準備工作:

建立Mysql表

1.引入maven依賴:其中包括mybatis本身和逆向工程生成依賴

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <!--Mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <!--Mysql的驅動-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.13</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
    <!--log4j日誌的兩個核心jar-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.11.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.11.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
    <!--Mybatis工程逆向生成-->
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.5</version>
    </dependency>
  </dependencies>
<build>
    <finalName>mybatisTestDay1_2</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        
        <!--Mybatis-generator外掛,用於自動生成Mapper和POJO-->
        <plugin>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-maven-plugin</artifactId>
          <version>1.3.2</version>
          <configuration>
            <!--配置檔案的位置-->
            <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
            <verbose>true</verbose>
            <overwrite>true</overwrite>
          </configuration>
          <executions>
            <execution>
              <id>Generate MyBatis Artifacts</id>
              <goals>
                <goal>generate</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

 2.如果想在使用過程中檢視日誌輸出,需要在resources中新增log4j的配置檔案

<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="warn">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

3.關於逆向工程生成,可以看我另一篇博文

4.逆向生成好實體類、實體類的mapper對映檔案之後,寫mybatis配置檔案

<?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>
    <!-- 1、mybatis也可以使用properties來引入外部properties配置檔案的內容(主要還是配置資料庫賬號密碼)
               resource 引入類路徑下資源
               url 引入網路路徑或磁碟路徑下資源 -->
    <properties resource="dbConfig.properties"></properties>
    <!-- 2、settings包含很多重要的全域性引數設定,一般使用預設即可
             setting標識具體的設定項
                 name表示設定項的名字
                 value表示設定項的值 -->
    <settings>
        <!--設定開啟懶載入-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <!-- 3、typeAliases 為java型別起別名,在parameterType和resultType中就可以直接使用別名了
              typeAlias 為某個具體的java型別取別名
                   type java類的全類名,預設別名就是類名小寫
                   alias 自定義別名 -->
    <typeAliases>
        <typeAlias type="com.ogms.domain.User" alias="User" />
        <!-- package為某個包下面所有類批量起別名
           name 表示包的名稱 預設別名為類名小寫,在使用的的時候,首字母大小寫都可以
           這裡重複配置了User類,複製的時候注掉一種配置-->
        <!--<package name="com.ogms.domain" />-->
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <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>
        <!--單獨載入,根目錄是資源目錄resources-->
        <mapper resource="mappers/UserMapper.xml"/>
        <mapper resource="mappers/ItemMapper.xml"/>
        <mapper resource="mappers/OrdersMapper.xml"/>
        <mapper resource="mappers/OrderdetailMapper.xml"/>
        <mapper resource="mappers/OrdersUserMapper.xml"/>
        <mapper resource="mappers/UserItemVoMapper.xml"/>
        <mapper resource="mappers/OrdersUserLazyLoadingMapper.xml"/>
        <!--批量載入,根目錄是類的根目錄java,即將UserMapper.xml放在com.ogms.configs下-->
        <!--<package name="com.ogms.configs"></package>-->
    </mappers>
</configuration>

5.獲取SqlSession的類:

package com.ogms.dao;
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 java.io.IOException;
import java.io.InputStream;
/**
 * @Author: David.Xiao
 * @Date: 2018/11/17 15:52
 * @Description:
 */
public class MybatisUtils {
    static String resource = "mybatisConfig.xml";
    static SqlSessionFactory sqlSessionFactory;
    static SqlSession session;
    static InputStream inputStream;
    static {
        try {
            inputStream =  Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //建立Session工廠,用以產生session
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //得到session
        session = sqlSessionFactory.openSession();
    }
    public static SqlSession getSqlSession()
    {
        return session;
    }
}

6.一個訂單隻對應一個使用者,一對一查詢對映檔案及測試程式碼:

首先在Orders類中新增User物件

public class Orders {  
  private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    //...省略其它成員
}

寫OrdersUserMapper.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.ogms.domain.OrdersUserMapper" >
    <!--對映訂單關聯的使用者-->
    <resultMap id="UserOrderVoResultMap" type="com.ogms.vo.OrderUserVo" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="user_id" property="userId" jdbcType="BIGINT" />
        <result column="number" property="number" jdbcType="VARCHAR" />
        <result column="createtime" property="createtime" jdbcType="TIMESTAMP" />
        <result column="note" property="note" jdbcType="VARCHAR" />
        <result column="username" property="userName" jdbcType="VARCHAR"/>
        <result column="sex" property="sex" jdbcType="CHAR"/>
        <result column="address" property="address" jdbcType="VARCHAR"/>
        <!--用於對映一對一關聯查詢, 一個訂單關聯一個使用者,association表示被關聯的表和java實體類之間的對映關係
        property:要將關聯查詢的使用者資訊對映到Orders中哪個屬性,在此之前必須在Orders類中建立User user成員-->
        <association property="user" javaType="com.ogms.domain.User">
            <!--在 一個訂單隻關聯一個使用者 關聯中,column指定訂單表中唯一標識使用者的欄位-->
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
    <!--一對一查詢 對映訂單關聯的使用者-->
    <select id="queryOrdersUser" resultMap="UserOrderVoResultMap">
        SELECT orders.*,username,sex,address FROM orders,user where orders.user_id = user.id;
    </select>
</mapper>

在OrdersUserMapper介面類中新增方法:

public interface OrdersUserMapper {
    List<OrderUserVo> queryOrdersUser();
}

測試程式碼:

package com.ogms.dao;

import com.ogms.domain.OrdersUserMapper;
import com.ogms.vo.OrderUserVo;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
/**
 * @Author: David.Xiao
 * @Date: 2018/11/21 20:16
 * @Description:
 */
public class One2OneTest {
    @Test
    public void queryOrdersUser()
    {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //建立UserMapper代理物件
        OrdersUserMapper ordersUserMapper = sqlSession.getMapper(OrdersUserMapper.class);
        List<OrderUserVo> list = ordersUserMapper.queryOrdersUser();
        System.out.println(list);
    }
}

7.一對多對映檔案及測試程式碼

<?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.ogms.domain.UserMapper">
  <!--使用二級快取-->
  <cache/>
  <resultMap id="BaseResultMap" type="com.ogms.domain.User">
    <result column="id" jdbcType="BIGINT" property="id" />
    <result column="username" jdbcType="VARCHAR" property="username" />
    <result column="birthday" jdbcType="DATE" property="birthday" />
    <result column="sex" jdbcType="CHAR" property="sex" />
    <result column="address" jdbcType="VARCHAR" property="address" />
  </resultMap>

  <!--一對多對映:查詢每個使用者關聯的訂單-->
  <resultMap id="UserOrderResultMap" type="com.ogms.domain.User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="birthday" property="birthday"/>
    <result column="sex" property="sex"/>
    <result column="address" property="address"/>
    <collection property="ordersList" ofType="com.ogms.domain.Orders">
      <id column="id" property="id"/>
      <result column="user_id" property="userId"/>
      <result column="number" property="number"/>
      <result column="createtime" property="createtime"/>
      <result column="note" property="note"/>
    </collection>
  </resultMap>
  <!--一對多查詢:查詢每個使用者關聯的訂單-->
  <select id="queryUserOrder" resultMap="UserOrderResultMap">
        select user.*,user_id,number,createtime,note from user,orders where user.id = orders.user_id;
  </select>
  <select id="queryUserById" parameterType="int" resultMap="BaseResultMap">
    select user.* from user where id = #{user_id};
  </select>

</mapper>

在User實體類中新增OrderList成員

public class User {
    private List<Orders> ordersList;
    public List<Orders> getOrdersList() {
        return ordersList;
    }
    public void setOrdersList(List<Orders> ordersList) {
        this.ordersList = ordersList;
    }
    //省略其它成員    
}

UserMapper介面類:

public interface UserMapper {
    List<User> queryUserOrder();
    User queryUserById(int user_id);
}

測試程式碼:

package com.ogms.dao;

import com.ogms.domain.User;
import com.ogms.domain.UserMapper;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
/**
 * @Author: David.Xiao
 * @Date: 2018/11/22 14:47
 * @Description:
 */
public class One2ManyTest {
    /**
     * 一對多:查詢一個使用者關聯的訂單
     */
    @Test
    public void queryUserOrders()
    {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //建立UserMapper代理物件
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.queryUserOrder();
        System.out.println(userList);
    }
}

8.一個使用者關聯多個商品,一個商品也被多個使用者購買,多對多操作

建立一個UserItem實體類,其中包含要查詢出各個表中的欄位對應的成員

public class UserItemVo {
    private int id;
    private String username;
    private String address;

    private int order_id;
    private String order_number;
    private Date order_createtime;

    private int item_id;
    private int orderdetail_num;

    private String item_name;
    private Float item_price;
}

對映檔案:

<?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.ogms.domain.UserItemVoMapper" >
    <!--對映訂單關聯的使用者-->
    <resultMap id="UserItemVoResultMap" type="com.ogms.vo.UserItemVo" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="order_id" property="order_id"/>
        <result column="number" property="order_number"/>
        <result column="order_createtime" property="order_createtime"/>
        <result column="item_id" property="item_id"/>
        <result column="item_num" property="orderdetail_num"/>
        <result column="name" property="item_name"/>
        <result column="price" property="item_price"/>
    </resultMap>
    <!--多對多查詢 對映訂單關聯的使用者-->
    <select id="queryUserItems" resultMap="UserItemVoResultMap">
        SELECT user.id,username,address,orders.id order_id,number,orders.createtime order_createtime,item.id item_id,item_num,name,price  FROM orders,user,orderdetail,item
        where orders.user_id = user.id and orderdetail.order_id = orders.id and item.id = orderdetail.item_id;
    </select>
</mapper>

介面類:

public interface UserItemVoMapper {
    List<UserItemVo> queryUserItems();
}

測試程式碼:

public class Many2ManyTest {
    /**
     * 多對多:查詢一個使用者關聯的訂單
     */
    @Test
    public void queryUserOrders()
    {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //建立UserMapper代理物件
        UserItemVoMapper userItemVoMapper = sqlSession.getMapper(UserItemVoMapper.class);
        List<UserItemVo> userList = userItemVoMapper.queryUserItems();
        for (UserItemVo useritem:userList) {
            System.out.println(useritem);
        }
    }
}