1. 程式人生 > >【開課吧javaEE每日一學190803】mybatis開發DAO層與SqlMapConfig.xml配置檔案

【開課吧javaEE每日一學190803】mybatis開發DAO層與SqlMapConfig.xml配置檔案

原始開發方式

實現流程

  • 編寫SqlMapConfig.xml配置檔案和mapper.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 resource="db.properties"></properties>
    		<environments default="development">
    			<environment id="development">
    				<transactionManager type="JDBC"/>
    				<dataSource type="POOLED">
    					<property name="driver" value="${db.driver}"/>
    					<property name="url" value="${db.url}"/>
    					<property name="username" value="${db.username}"/>
    					<property name="password" value="${db.password}"/>
    				</dataSource>
    			</environment>
    		</environments>
    		<mappers>
    			<mapper resource="UserMapper.xml"/>
    		</mappers>
    	</configuration>
    
    資料庫配置檔案
    	db.driver=com.mysql.jdbc.Driver
    	db.url=jdbc:mysql://localhost:3306/ssm
    	db.username=root
    	db.password=admin
    
    UserMapper.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">
    	<!--namespace作用是為了分類管理對映檔案中的MapperdStatement物件-->
    	<mapper namespace="test">
    		<select id="findUserById" parameterType="int" resultType="test.User">
    		select * from User where id = #{hello}
    	  </select>
    
    		<!--${value}表示輸入引數將${value}替換,直接做字串的拼接,如果是取簡單數量型別的引數,括號中的引數名必須是value-->
    		<select id="findUserByUsername" parameterType="java.lang.String" resultType="test.User">
    		  select * from user where username like '%${value}%'
    		</select>
    
    		<insert id="insertUser" parameterType="test.User">
    			<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    				select LAST_INSERT_ID()
    			</selectKey>
    			insert into user(username, birthday, sex, address)
    			values (#{username}, #{birthday}, #{sex}, #{address})
    		</insert>
    	</mapper>
    
    上面使用like的時候用的是$而不是#,至於$和#的區別看$和#的區別
  • 開發介面(DAO層介面)
    	package top.dao;
    
    	import test.User;
    
    	public interface UserDao {
    		User findUserById(int id) throws Exception;
    		void insertUser(User user) throws Exception;
    	}
    
  • 實現介面(DAO實現類,在實現類中通過sqlsesion與資料庫打交道)
    	package top.dao.impl;
    
    	import org.apache.ibatis.session.SqlSession;
    	import org.apache.ibatis.session.SqlSessionFactory;
    	import test.User;
    	import top.dao.UserDao;
    
    	public class UserDaoImpl implements UserDao {
    
    		private SqlSessionFactory sqlSessionFactory;
    
    	//    注入sqlsessionFactory
    		public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
    			this.sqlSessionFactory = sqlSessionFactory;
    		}
    
    		@Override
    		public User findUserById(int id) throws Exception {
    			SqlSession sqlSession = sqlSessionFactory.openSession();
    			User user = sqlSession.selectOne("test.findUserById", id);
    			sqlSession.close();
    			return user;
    		}
    
    		@Override
    		public void insertUser(User user) throws Exception {
    			SqlSession sqlSession = sqlSessionFactory.openSession();
    			sqlSession.insert("test.insertUser", user);
    			sqlSession.commit();
    			sqlSession.close();
    		}
    	}
    
  • 測試類
    	@Test
    		public void testFindById() throws Exception {
    			UserDao userDao = new UserDaoImpl(sqlSessionFactory);
    			User user = userDao.findUserById(1);
    			System.out.println(user);
    		}
    

幾個物件的生命週期

  • sqlSession: 方法級別

    所謂的方法級別就是需要在方法裡面建立的物件

  • sqlSessionFactory: 全域性範圍,是應用級別

  • sqlSessionFactoryBuilder: 方法級別

mapper代理開發方式(xml配置檔案)

mapper代理開發方式就是使用介面開發方式,上面使用原始的dao進行開發的時候不僅僅建立了dao介面,還有dao的實現類,我們是在實現類裡面去建立sqlsession物件來操作資料庫的,現在所謂的mapper代理開發方式就是去掉dao的實現類,只需要保留介面即可,但是使用mapper代理方式開發是有前置條件的。具體條件如下:

  • mapper介面的類路徑需要與mapper.xml檔案中的namespace相同 這裡需要注意的是類路徑而不是包路徑,如果是寫的包路徑就會出現下面的錯誤 org.apache.ibatis.binding.BindingException: Type interface top.mapper.UserMapper is not known to the MapperRegistry.
  • mapper介面的方法名稱需要和mapper.xml中定義的每一個statement的id相同
  • mapper介面的方法輸入引數型別需要和mapper.xml中定義的每一個sql的parameterType的型別相同
  • mapper介面的方法的輸出引數型別和mapper.xml中定義的每一個sql的resultType的型別相同 依然是上面的案例進行修改:

mapper檔案

<?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">
<!--namespace作用是為了分類管理對映檔案中的MapperdStatement物件-->
<mapper namespace="top.mapper.UserMapper">
    <select id="findUserById" parameterType="int" resultType="test.User">
    select * from User where id = #{hello}
  </select>

    <!--${value}表示輸入引數將${value}替換,直接做字串的拼接,如果是取簡單數量型別的引數,括號中的引數名必須是value-->
    <select id="findUserByUsername" parameterType="java.lang.String" resultType="test.User">
      select * from user where username like '%${value}%'
    </select>

    <insert id="insertUser" parameterType="test.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user(username, birthday, sex, address)
        values (#{username}, #{birthday}, #{sex}, #{address})
    </insert>
</mapper>

這裡可以看到mapper檔案中namespace已經改了,是mapper介面的類路徑。

mapper介面

package top.mapper;

import test.User;

public interface UserMapper {
    User findUserById(int id) throws Exception;
    void insertUser(User user) throws Exception;
}

測試程式碼

package test;


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 top.mapper.UserMapper;
import top.mapper.impl.UserMapperImpl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class TestUser {

    // 會話工廠
    private SqlSessionFactory sqlSessionFactory;

    // 該註解可以在@test註解之前執行
    @Before
    public void createSqlSessionFactory() throws IOException {
        // 載入配置檔案
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 使用sqlSessionFactoryBuilder從xml中建立sqlsessionfactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testMapperFind() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        獲取mapper介面的代理物件
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 呼叫代理物件方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
        sqlSession.close();
    }
}

SqlMapperConfig.xml配置檔案常用的標籤

mybatis的主配置檔案可以配置如下所示的標籤:

  • properties(屬性,可以將外部的屬性檔案載入進來。比如資料庫的配置檔案)
    • <!--載入配置檔案--> <properties resource="db.properties"></properties>

    • 除了使用resource屬性之外還可以使用properties標籤中定義property子標籤來定義資料可屬性值

      	<properties>
      	<property name="driver" value="com.mysql.jdbc.Driver"/>
      	</properties>
      
    • mybatis是先讀取properties元素體內的屬性,然後再去讀取url或者resource載入的屬性,此時會覆蓋已讀取的同名的屬性。

  • settings(全域性配置引數)
  • typeAlias標籤,定義別名的
    • 批量或者單個定義別名
      	<typeAliases>
      <!--定個定義別名-->
      <!--<typeAlias type="test.User" alias="user"/>-->
      <!--批量定義別名.掃描整個包下面的類,別名為類名(首字母大小或小寫都可以)-->
      <package name="test"/>
      	</typeAliases>
      
  • mappers標籤
    • <mapper resource=" " />(單個)
      • 使用相對於類路徑的資源
      • 案例: <mapper resource="sqlmap/User.xml" />
    • <mapper class=" " />(單個)
      • 使用的是介面類路徑
      • 案例: <mapper class="com.kkb.mybatis.mapper.UserMapper"/>
      • 此時需要注意的是要求mapper介面名稱和mapper對映檔名稱相同,並且應該放在同一個目錄中
    • <package name=""/>(批量)
      • 註冊指定包下的所有mapper介面,來載入對映檔案
      • 案例:<package name="com.kkb.mybatis.mapper"/>
      • 使用批量的方式要求mapper介面名稱和mapper對映檔案的名稱相同,並且放在同一個目錄中