1. 程式人生 > >用mybatis實現dao的編寫或者實現mapper代理

用mybatis實現dao的編寫或者實現mapper代理

new 二級緩存 1.0 rate 函數 對象 orm log java

一、mybatis和hibernate的區別和應用場景
hibernate:是一個標準的ORM框架(對象關系映射)。入門門檻較高的,不需要寫sql,sql語句自動生成了。對sql語句進行優化、修改比較困難的。
應用場景:使用與需求變化不多的中小型項目,比如:後臺管理系統,erp、orm、oa
mybatis:專註是sql本身,需要程序員寫sql,修改優化比較方便。也可以實現映射。
應用場景:使用需求變化較多的項目,比如:互聯網項目,

二、實現dao的編寫(以user為例)

1、編寫userDAO

package dao;

import entity.users;

public interface
UserDao { public users findUserByid(int id) throws Exception; public void insertUser(users user) throws Exception; public void updateUser(users user) throws Exception; public void deleteUser(users user) throws Exception; }

2、編寫userDaoImpl

因為現在沒有和spring整合,所以SqlSessionFactory當工具類使用,用構造函數的方式註入,以後會交給spring管理

package dao;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import entity.users;

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory sqlSessionFactory=null;
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
        
this.sqlSessionFactory=sqlSessionFactory; } @Override public users findUserByid(int id) throws Exception { SqlSession sqlSession=sqlSessionFactory.openSession(); users u=sqlSession.selectOne("test.srarchByid", id); System.out.println(u.getBirthday().toString()); sqlSession.close(); return u; } @Override public void insertUser(users user) throws Exception { SqlSession sqlSession=sqlSessionFactory.openSession(); sqlSession.insert("test.insertUser", user); System.out.println(user.getId()); sqlSession.commit(); sqlSession.close(); } @Override public void updateUser(users user) throws Exception { // TODO Auto-generated method stub SqlSession sqlSession=sqlSessionFactory.openSession(); sqlSession.update("updateUser",user); System.out.println(user.getId()); sqlSession.commit(); sqlSession.close(); } @Override public void deleteUser(users user) throws Exception { // TODO Auto-generated method stub SqlSession sqlSession=sqlSessionFactory.openSession(); sqlSession.delete("test.deleteUser",3); sqlSession.commit(); sqlSession.close(); } }

3、測試類

這裏只測試了根據ID查詢和插入,其他的類型,在這裏不一一測試了。

package dao;

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

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import entity.users;

public class UserDaoImplTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void setUpBeforeClass() throws Exception {
        String resource="SqlMapConfig.xml";
        InputStream stream=Resources.getResourceAsStream(resource);
        sqlSessionFactory=new SqlSessionFactoryBuilder().build(stream);
    }

    @Test
    public void testFindUserByid() throws Exception {
        UserDao userDao=new UserDaoImpl(sqlSessionFactory);
        users u=userDao.findUserByid(1);
        System.out.println(u.getName());
        
    }

    @Test
    public void testInsertUser() throws Exception {
        users user=new users();
        user.setName("王五");
        user.setSex("f");
        user.setAddress("五道口");
        user.setBirthday(new Date());
        UserDao userDao=new UserDaoImpl(sqlSessionFactory);
        userDao.insertUser(user);
        
    }

}

三、原始DAO開發問題  

1.DAO的接口實現類方法中存在大量的模板方法。
2、調用SQLSession方法時將statement硬編碼了。
3、調用SQLSession方法時傳入的變量,由於sqlsession方法使用泛型,即使參數類型錯誤,編譯階段不報錯。

由於以上的問題,mybatis提出了mapper代理的概念。這個概念的提出有效的解決了以上提出的問題,程序員只需要開發mapper代理(類似於dao的接口),框架自動為其生成實現類。下面將詳細介紹mapper的開發步驟。

四、mapper代理的開發(同樣以user為例)

1、開發規範

1)在mapper.xml namespace等於mapper接口地址
2)mapper.java接口的方法名與mapper.xml的statement中得id一致
3)mapper.java接口中得方法輸入參數和mapper.xml中得statement的parameter指定的類型一致。
4)接口返回值類型與statement中resultType類型一致。

2、代碼實現

1)編寫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">

<!--mapper代理開發,namespace要與mapper接口的全名地址一樣-->
<mapper namespace="mapper.UserMapper">
    <select id="findUserByid" parameterType="int" resultType="entity.users">
        select * from users where id=#{id}
    </select>
    <select id="findUserByName" parameterType="String" resultType="entity.users">
        select * from users where name like ‘%${value}%‘
    </select>
    <insert id="insertUser" parameterType="entity.users">
        insert into users(name,birthday,address,sex) values(#{name},#{birthday},#{address},#{sex})
        <selectKey keyProperty="id" order="AFTER" resultType="int">
            select last_insert_id()
        </selectKey>
    </insert>
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from users where id=#{id}
    </delete>
    <update id="updateUser" parameterType="entity.users">
        update users set name=#{name},address=#{address},birthday=#{birthday},sex=#{sex} where id=#{id}
    </update>

</mapper>

在上一篇博文中我們開發了user.xml,這個是在開發普通dao時使用的配置文件,這裏的userMapper與其功能類似。但需要註意的是namespace要與mapper接口的全名地址一樣,mapper的ID要與mapper代理中得接口方法名相同。

2)mapper代理接口

package mapper;

import java.util.List;

import entity.users;

public interface UserMapper {
    public users findUserByid(int id) throws Exception;
    public List<users> findUserByName(String name) throws Exception;
    public void insertUser(users user) throws Exception;
    public void updateUser(users user) throws Exception;
    public void deleteUser(int id) throws Exception;
    

}

3)測試代碼

package mapper;

import static org.junit.Assert.fail;

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 entity.users;

public class UserMapperTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void setUp() throws Exception {
        String resource="SqlMapConfig.xml";
        InputStream stream=Resources.getResourceAsStream(resource);
        sqlSessionFactory=new SqlSessionFactoryBuilder().build(stream);
    }

    @Test
    public void testFindUserByid() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        users user=userMapper.findUserByid(5);
        System.out.println(user.getName());
    }

    @Test
    public void testFindUserByName() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        List<users> list=userMapper.findUserByName("王");
        for(users u:list){
            System.out.println(u.getName());
        }
    }

    @Test
    public void testInsertUser() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        users user=new users();
        user.setName("Danny");
        user.setAddress("America");
        user.setBirthday(new Date());
        user.setSex("f");
        userMapper.insertUser(user);
        sqlSession.commit();
        sqlSession.close();
        System.out.println(user.getId());
    }

    @Test
    public void testUpdateUser() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        users user=new users();
        user.setId(19);
        user.setName("Danny");
        user.setAddress("America");
        user.setBirthday(new Date());
        user.setSex("m");
        userMapper.updateUser(user);
        sqlSession.commit();
        sqlSession.close();
        System.out.println(user.getId());
    }

    @Test
    public void testDeleteUser() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUser(19);
        sqlSession.commit();
        sqlSession.close();
    }

}

mapper開發步驟總結為一下三個步驟
1)程序員還需要編寫mapper.xml映射文件
2)編寫mapper接口
3)mybatis自動生成mapper接口的實現類對象

五、SQLMapConfig中得其他配置內容

1.properties

需求:將數據庫的連接參數單獨配置在db.properties中,只需要在Sqlmapconfig.xml中加載db.properties的屬性值,不需要再Sqlmapconfig.xml中硬編碼了

操作:

新建一個db.properties,內容如下:

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

然後在Sqlmapconfig.xml中加入以下標簽

<properties resource="db.properties"> </properties> ,這個標簽要被<configuration>包住。同時可以在properties中再配置property,實現新的屬性值,它會覆蓋resource中得同名屬性

通過以上步驟就實現了數據庫連接字符串的非硬編碼實現。

註意!Mybatis將按照下面的順序來加載屬性:
在properties元素體內定義的屬性首先被讀取
然後會讀取properties元素中resource或url加載的屬性,它會覆蓋已讀取得同名屬性
在最後讀取parameterType傳遞的屬性,它會覆蓋已讀取得同名屬性。
2.setting全局的參數配置
用來調整一些運行參數,例如二級緩存和延遲加載。

3.typeAliaes

在mapper.xml中,定義很多的statement,statement需要parameterType和rusultType指定參數的類型,
但是指定的類型要求是全路徑的,不方便開發,就可以針對這些個全路徑名字定義別名來實現。

操作:

(1)針對單個別名定義

在Sqlmapconfig.xml中添加以下內容

<typeAliases>
        <typeAlias type="entity.users" alias="user"/>
  </typeAliases> 

然後在userMapper.xml中就可以用user代替entity.users

(2)可以直接對整個package做別名定義,指定報名後,將自動掃描包中得類自動定義別名,別名為類名,首字母可大寫也可小寫。

<typeAliases>
  <package name="entity"/>
</typeAliases>

4.mapper

這個標簽除了使用上面的resource屬性外,還可以使用class,通過mapper接口加載映射文件

需要遵循一些規範:需要mapper的類名和mapper.xml的名字一樣且在一個目錄下。

同樣class屬性支持package批量加載。

用mybatis實現dao的編寫或者實現mapper代理