MyBatis(二)

1、輸入輸出映射

一、輸入類型parameterType

1.1 傳遞基本類型

1.2 傳遞POJO對象

使用ONGL表達式解析對象字段的值,#{}或者${}中的值爲POJO屬性的名稱  user.usernamejava

1.3 傳遞POJO包裝對象QueryVo

查詢條件是多個查詢條件的綜合mysql

1.3.1 QueryVospring

public class QueryVo {

    private User user;

    public User getUser() {
        returnuser;
    }

    publicvoid setUser(User user) {
        this.user = user;
    }
}

1.3.2 UserMapper.xmlsql

<!-- 使用包裝類型查詢用戶 使用ognl從對象中取屬性值,若是是包裝對象可使用.操做符來取內容部的屬性
    -->
    <select id="findUserByQueryVo" parameterType="com.guojie.pojo.QueryVo" resultType="user">
        SELECT * FROM user where username like '%${user.username}%' and sex=#{user.sex}  // 查詢條件爲多個時,入參類型須要爲POJO
parameterType
</select>

1.3.3 UserMapper接口中數據庫

public List<User> findUserByQueryVo(QueryVo vo);

1.3.4 測試apache

@Test
public void testFindUserByQueryVo() throws Exception {
     SqlSession sqlSession = sessionFactory.openSession();
     //得到mapper的代理對象,經過getMapper方法實例化接口
     UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建立QueryVo對象 QueryVo queryVo = new QueryVo(); //建立user對象 User user = new User(); user.setUsername("劉"); user.setSex("1"); queryVo.setUser(user);
//根據queryvo查詢用戶 List<User> list = userMapper.findUserByQueryVo(queryVo); System.out.println(list); sqlSession.close();
}

 

二、輸出類型resultType

2.1 輸出基本類型

2.1.1 UserMapper.xml數組

<!-- 獲取用戶列表總數 -->
    <select id="findUserCount" resultType="int">
       select count(*) from user
    </select>

2.1.2 UserMapper接口session

public int findUserCount() throws Exception;

2.1.3 測試mybatis

Public void testFindUserCount() throws Exception{
    //獲取session
    SqlSession session = sqlSessionFactory.openSession();
    //獲取mapper接口實例
    UserMapper userMapper = session.getMapper(UserMapper.class);

    int count = userMapper.findUserCount();
        
    //關閉session
    session.close();
}

2.2 輸出POJO對象

2.3 輸出POJO列表

 

三、resultMap(用List可取代)

resultType須要POJO屬性和sql查詢的列名一致才能將查詢結果映射爲POJO,自動映射oracle

resultMap在POJO屬性和sql查詢的列名不一致時也行,可用於映射覆雜類型的POJO,須要手動配置

<select id="selectOrderList" resultMap="orders">
     select user_id, user_name from user
</select>
<resultMap type="Orders"  id="orders">
     <result column="user_id" property="userId">
</resultMap>

id:結果集的惟一標識

property:POJO類的屬性

column:sql字段

 

2、動態sql

經過MyBatis提供的各類標籤方法實現動態拼接sql

 一、<if>&<where>

<select id="findUserByNameAndSex" parameterType="cn.guojie.pojo.User" resultType="cn.guojie.pojo.User">
  <where>
      <if test="username!=null and username!=' ' ">
          and username like '%${username}%'
      </if>
      <if test="sex!=null and sex!=' ' ">
          and sex=#{sex}
      </if>
  <where>
</select>

where做用:添加where關鍵字,去掉第一個條件的and關鍵字

條件中username爲POJO的屬性

 

二、sql片斷<sql>

提取重複的sql條件封裝重用

<sql id="userFileds">
    重複代碼
</sql>
<select>
  <!--調用sql條件 -->
    <include refid="userField" />
</select>

 

三、<foreach>

向sql傳數組或list

<select id="findUserByIds" parameterType="cn.guojie.pojo.QueryVo" resultType="com.guojie.pojo.User">
    <where>
        <!-- ids爲QueryVo中的List集合屬性 -->
        <if test="ids"!=null>
            <foreach collection="ids" item="id" open="id in ("  close=")「 seperator="," 」>
                #{id}
            </foreach>
        </if>
    </where>
</select>

等同於select * from user whereid in (1, 2, 3)

collection:傳入的集合變量名

item:循環的數據存入變量

open:開始拼接的字符串

close:結束拼接的字符串

seperator:分隔符

sql中不要有or,會形成性能降低,用in

@Test
public void testFindUserByIds() throws Execption {
  SqlSession openSession = factory.openSession();
  // 經過getMapper方法實例化接口
  UserMapper mapper =  openSession.getMapper(UserMapper.class);
  
  QueryVo vo = new QueryVo();  
  List<Integer> ids = new ArrayList<Integer>();
  ids.add(1);
  ids.add(2);
  ids.add(3);
  vo.setIds(ids);

  List<User> list = mapper.findUserByIds(vo);
}    

 

3、關聯查詢

多中有一的屬性引用,一中有多的集合引用

一、一對一查詢

以訂單爲中心,單個訂單隻能屬於一個用戶,相對用戶一對一,訂單表以用戶表的id爲外鍵

互聯網通常單表查詢多,關聯查詢較少

1.1 方式一:自動映射(經常使用) resultType

根據表的字段名和POJO類中的屬性名對應

select a.*, b.id uid, username, birthday, sex, address 
from orders a, user b
where a.userId = b.id

1.1.1 自定義OrdersCustom

包含用戶和訂單中全部屬性或者繼承Orders類,再加上User類的屬性

public class OrdersCustom extends Orders {

    private String username;// 用戶名稱
    private String address;// 用戶地址
        setter&getter;
}
<!-- 查詢全部訂單信息 -->
<select id="findOrdersList" resultType="cn.guojie.mybatis.pojo.OrdersCustom">
    select a.*, b.id uid, username, birthday, sex, address 
    from orders a, user b
    where a.user_id = b.id
</select>
public void testfindOrdersList() throws Exception{
     //獲取session
     SqlSession session = sqlSessionFactory.openSession();
     //獲取mapper接口實例
     UserMapper userMapper = session.getMapper(UserMapper.class);
     //查詢訂單信息
     List<OrdersCustom> list = userMapper.findOrdersList();
     System.out.println(list);
     //關閉session
     session.close();
}

 

1.2 方式二:手動映射(MyBatis官方)  resultMap

指定表中字段名和POJO類中的屬性名的對應關係

用association完成關聯查詢

1.2.1 在Orders類中加入User對象

private User user;

1.2.2 OrderMapper.xml中

<!-- 查詢訂單關聯用戶信息使用resultmap -->
    <resultMap type="cn.guojie.pojo.Orders" id="orderUserResultMap">
         <!-- id爲主鍵字段,column爲表字段,property爲POJO屬性,result爲非主鍵字段 -->
        <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"/>
        <!-- 一對一關聯映射 -->
        <!-- 
        爲Order中增長的user對象設置對應關係
        property : Orders對象的user屬性
        javaType:user屬性對應的類型
         -->
        <association property="user" javaType="cn.guojie.pojo.User">
            <!-- column:user表的主鍵對應的列  property:user對象中id屬性-->
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
<select id="findOrdersList" resultMap="orderUserResultMap">
    select a.*, b.id uid, username, birthday, sex, address 
    from orders a, user b
    where a.user_id = b.id
</select>

1.2.3 OrderMapper接口中

public List<Orders> findOrdersList();

 1.2.4 測試

public void testfindOrdersListResultMap() throws Exception{
     //獲取session
     SqlSession session = sqlSessionFactory.openSession();
     //獲取mapper接口實例
     UserMapper userMapper = session.getMapper(UserMapper.class);

     //查詢訂單信息
     List<Orders> list = userMapper.findOrdersList();
   System.out.println(list);
   //關閉session  
   session.close();
 }

 

 二、一對多查詢

以用戶爲中心,一個用戶對應多個訂單

只能手動映射,在User類中加入Order的List<Orders>集合

private List<Orders> orderList;
<resultMap type="cn.guojie.pojo.user" id="userOrderResultMap">
        <!-- 用戶信息映射 -->
        <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""/>

        <!-- 
        一對多關聯映射 集合對象關係映射 
       property:將數據放入User對象中的orderList屬性中
       ofType:指定orderList屬性的泛型類型
         -->
        <collection property="orders" ofType="cn.guojie.pojo.Orders">
          <id column="oid property="id" "/>    
            <!--用戶id已經在user對象中存在,此處能夠不設置-->
            <!-- <result  column="id property="userId""/> -->
            <result column="number property="number" "/>
            <result column="createtime property="createtime" "/>
            <result  column="note property="note""/>
        </collection>
    </resultMap>
        
<select id="finUserAndOrders" resultMap="userOrderResultMap">
      select a.*, b.id oid, number,createtime
      from user a, order b 
      where a.id = b.user_id
</select> 
public List<User> findUserAndOrders();
@Test
public void testFindUserAndOrders() {
    SqlSession session = sqlSessionFactory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    List<User>result = userMapper.getUserOrderList();
    for (User user : result) {
        System.out.println(user);
    }
    session.close();
}

 

4、Spring整合MyBatis

一、思路

(1)數據庫鏈接池及其事務管理應交給Spring容器管理

(2)SqlSessionFactory工廠對象應該放到Spring容器中做爲單例對象

(3)傳統DAO開發中,應從Spring容器中得到sqlSession對象;Mapper動態代理形式中,應從Spring容器中得到mapper的接口代理對象

二、整合

2.1 導包

Spring 、MyBatis、Spring+MyBatis整合包、MySQL數據庫驅動包、數據庫鏈接池DBCP(比C3P0效率低)

2.2 Spring核心配置文件applicationContext.xml

<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 加載配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- 數據庫鏈接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="10"/>
        <property name="maxIdle" value="5"/>
    </bean>
    <!-- mapper配置 -->
    <!-- 讓spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 數據庫鏈接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 加載mybatis的全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
    </bean>
</beans>

Spring容器配置文件須要加classpath

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

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>
    <typeAliases>
        <package name="cn.guojie.mybatis.pojo"/>
    </typeAliases>
    <mappers>
        <mapperresource="sqlmap/User.xml"/>
    </mappers>
</configuration>

三、原生DAO

接口+實現類,實現類繼承自SqlSessionSupport類,提供getSqlSession()來獲取SqlSession

須要在Spring配置文件中指定DAO類

DAO實現類須要繼承SqlSessionDaoSupport超類

在DAO實現類中不要手動關閉會話,不要提交事務

applicationContext.xml中

<!-- 配置UserDao實現類 -->
<bean id="userDao" class="cn.guojie.dao.UserDaoImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

DAO實現類

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {

    @Override
    public User findUserById(int id) throws Exception {
        SqlSession session = this.getSqlSession();
        User user = session.selectOne("test.findUserById", id);
        //不能關閉SqlSession,讓spring容器來完成
        //session.close();
        return user;
    }

    @Override
    public void insertUser(User user) throws Exception {
        SqlSession session = this.getSqlSession();
        session.insert("test.insertUser", user);
        session.commit();
        //session.close();
    }
}

測試

public class UserDaoTest {
    private ApplicationContext applicationContext;
    @Before
    public void setUp() throws Exception{
    String configLocation = "classpath:spring/ApplicationContext.xml";
    //初始化spring運行環境
    applicationContext = new ClassPathXmlApplicationContext(configLocation);
    }

    @Test
    public void testFindUserById() throws Exception {
    UserDao userDao = (UserDao) applicationContext.getBean("userDao");
    User user = userDao.findUserById(1);
    System.out.println(user);
    }
}

四、Mapper接口動態代理

只須要接口,由MyBatis生成其實現類

applicationContext.xml中

方式一

<!-- 配置mapper代理對象 -->
<bean id=userMapper class="org.mybatis.spring.mapper.MapperFactoryBean">
    <!-- 配置mapper接口全路徑名-->
    <property name="mapperInterface" value="cn.guojie.mybatis.mapper.UserMapper"/>            
    <propertyname="sqlSessionFactory"ref="sqlSessionFactory"></property>
</bean>
public class UserMapperTest {

    private ApplicationContext applicationContext;

    @Before
    publicvoid setUp() throws Exception {
        applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    }

    @Test
    public void testGetUserById() {
        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
        User user = userMapper.getUserById(1);
        System.out.println(user);
    }

}

方式二:包掃描批量引入Mapper(經常使用

<!-- 使用掃描包的形式來建立mapper代理對象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.guojie.mybatis.mapper"></property>
</bean>

每一個mapper代理對象的id就是類名,掃描後引用時首字母小寫

SqlMapConfig.xml中<package name="cn.guojie.mapper"/>包掃描批量引入接口能夠不要了,重複引用

 

5、MyBatis逆向工程

一、導包

MyBatis核心包

數據庫驅動

逆向工程包

日誌包log4j-1.2.16.jar

二、generator.xml   工程目錄下

(1)POJO所在的包路徑注意修改

(2)添加要生成的數據庫表

(3)mapper文件和接口所在的包路徑要一致

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="testTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自動生成的註釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--數據庫鏈接的信息:驅動類、鏈接地址、用戶名、密碼 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root"
            password="admin">
        </jdbcConnection>
        <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
            connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 
            userId="yycg"
            password="yycg">
        </jdbcConnection> -->

        <!-- 默認false,把JDBC DECIMAL 和 NUMERIC 類型解析爲 Integer,爲 true時把JDBC DECIMAL 和 
            NUMERIC 類型解析爲java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetProject:生成POJO類的位置 -->
        <javaModelGenerator targetPackage="cn.guojie.pojo"
            targetProject=".\src">
            <!-- enableSubPackages:是否讓schema做爲包的後綴 -->
            <property name="enableSubPackages" value="false" />
            <!-- 從數據庫返回的值被清理先後的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置,和接口放在同一目錄 -->
        <sqlMapGenerator targetPackage="cn.guojie.mapper" 
            targetProject=".\src">
            <!-- enableSubPackages:是否讓schema做爲包的後綴 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- targetPackage:mapper接口生成的位置 和映射文件放在同一目錄 -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="cn.guojie.mapper" 
            targetProject=".\src">
            <!-- enableSubPackages:是否讓schema做爲包的後綴 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 指定數據庫表 -->
<!--         <table tableName="items"></table> -->
        <table tableName="orders"></table>
<!--         <table tableName="orderdetail"></table> -->
        <table tableName="user"></table>
        <!-- <table schema="" tableName="sys_user"></table>
        <table schema="" tableName="sys_role"></table>
        <table schema="" tableName="sys_permission"></table>
        <table schema="" tableName="sys_user_role"></table>
        <table schema="" tableName="sys_role_permission"></table> -->
        
        <!-- 有些表的字段須要指定java類型
         <table schema="" tableName="">
            <columnOverride column="" javaType="" />
        </table> -->
    </context>
</generatorConfiguration>

三、使用Java類生成mapper文件(mapper接口+mapper.xml+POJO類)

public class StartServer {
    
    public void generator() throws Exception{
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("genarator.xml"); 
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                callback, warnings);
        myBatisGenerator.generate(null);
    }

    public static void main(String[] args) throws Exception {
        try {
            StartServer startServer = new StartServer();
            startServer.generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

生成文件的方式是追加而不是覆蓋,運行第二次會再生成一遍,要刪除原來的再生成,否則會報錯

四、拷貝生成的文件

mapper xml文件和mapper.java文件在一個目錄內且文件名相同

五、測試

public class UserMapperTest {
    private ApplicationContext applicatonContext;
    
    @Before
    public void setUp() throws Exception{
        String configLocation = "classpath:ApplicationContext.xml";
        applicatonContext = new ClassPathXmlApplicationContext(configLocation);
    }
        
    @Test
    public void testFindUserById() throws Exception{
        UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper");
        
        User user = userMapper.selectByPrimaryKey(1);
        System.out.println(user);
    }
    
    @Test
    public void testFindUserAndSex() throws Exception{
        UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper");
        
        //建立UserExample對象
        UserExample userExample = new UserExample();
        //經過UserExample對象建立查詢條件封裝對象(Criteria中是封裝的查詢條件)
        Criteria createCriteria = userExample.createCriteria();
        
        //加入查詢條件
        createCriteria.andUsernameLike("%王%");
        createCriteria.andSexEqualTo("1");
        
        List<User> list = userMapper.selectByExample(userExample);
        System.out.println(list);
    }
}

like模糊查詢時要加%

 

POJO:不按MVC分層,只有JavaBean的一些屬性和setter&getter

Domain:不按MVC分層,只有JavaBean的一些屬性和setter&getter

PO:用於持久層,在增長或者修改的時候,從頁面直接傳入action中,其中JavaBean類名等於表名,屬性名等於字段名,還有對應的setter&getter

VO:View Object表現層對象,主要用於在高級查詢中從頁面接收傳過來的各類條件參數,好處是擴展性強

BO:在Service,如今基本不用

相關文章
相關標籤/搜索