談jdbcTemplate與mybatis


為什么會產生 Hibernate Mybatis 這類的dao層框架

傳統的jdbc 雖然執行速度很快,但是開發效率很低,隨着面向對象開發的設計思想,在面向對象編程中 將對象 進行持久化,存入關系型的數據庫時,由於關系型數據庫的設計思想是數學思維,在持久化時,必須要對象拆分各個屬性值,才可存入數據庫;傳統的jdbc 持久化時 對象持久化時 ,取出對象的一個一個屬性,過去繁瑣,並且不便於維護,而市場上的面向對象的數據庫還並不成熟,所以為了調節面向對象設計的開發思想與落后的關系型數據庫之間持久化時繁瑣的問題,產生了一種新的設計規范

ORM (Object Relation Mapping) 

對象關系映射,是一種規范,調節目前面向對象的程序設計與主流的關系型數據庫之間 發展不同步的問題,
關系 到對象的映射;
讓編程時 可以全身心的用面向對象的設計思想去編程, 用對象映射關系數據表,在持久化時,可以直接操作對象進行持久化。
優點:
開發效率高;
可維護性高;
缺點:
高效率的開發 對應也要失去性能,處理復雜關系時,性能會變差;
 

Spring對數據庫的操作在jdbc上面做了深層次的封裝,也就是工具類 jdbcTemplate

先看一下jdbcTemplate的大致流程圖

作用:

1: 它提供了AOP式的事務管理

AOP式的事物管理:在以前的事務管理是要融合在邏輯代碼中的,在邏輯代碼中決定事務是否提交或者回滾,這樣很容易造成代碼難以維護,代碼冗余
但是使用spring的聲明式事務后,只需要在數據庫處理方法上注解事務,就可以對操作進行管理,事務的設置和邏輯代碼分開,容易維護。

不修改原有代碼 重新封裝現有的組件
類似於: FileWrite fw = new FileWrite();
PrintWrinter pw = new Prinwriter(fw);
2:spring 提供了統一的異常處理,框架處理了異常。
不論Dao層運用什么技術實現 出現的錯誤全部封裝成了DatyaAccessException
如何使用 
1 引入相應spring jar包 + 數據庫驅動包
2  在spring的主配置文件中配置 jdbcTemplate
<!-- 定義template組件 -->
    <bean id="template" 
        class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 注入連接信息 -->
        <property name="dataSource" ref="bonecp">
        </property>
    </bean>
 定義組件時 template需要一個數據連接池 來管理數據庫連接
數據連接池 有很多種 這里用的是
com.alibaba.druid.pool.DruidDataSource
<!-- DataSource 數據源 連接池 存儲管理大量的鏈接 流行的 dbcp c3p0,proxool -->
        <!-- 數據源配置, 使用 BoneCP 數據庫連接池 -->
    <bean id="bonecp" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
        <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass -->
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        
        <!-- 基本屬性 url、user、password -->
        <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&amp;characterEncoding=utf-8" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        
        <!-- 配置獲取連接等待超時的時間 -->
        <property name="maxWait" value="60000" />
        
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000" />
        
    
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        
        
        
        <!-- 配置監控統計攔截的filters -->
        <property name="filters" value="stat" /> 
    </bean>

下一部是根據表 編寫實體類

實體類

package com.mxp.jdbc.entity;

import java.io.Serializable;

public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String userName;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    

}

還需要根據實體類寫一個rowmapper

注意這里要繼承

org.springframework.jdbc.core.RowMapper,然后重寫maprow方法
package com.mxp.jdbc.entity;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

/** 
 * 每個實體類都有這個封裝組件
 * 將User記錄封裝成 User對象
 * @author Administrator
 *
 */
public class UserRowMapper implements RowMapper<User>{

    /**
     * arg1:第幾行記錄 
     */
    @Override
    public User mapRow(ResultSet arg0, int arg1) throws SQLException {
        User user = new User();
        user.setId(arg0.getString("id"));
        user.setUserName(arg0.getString("user_name"));
        return user;
    }

}

 下面可以編寫dao了 編寫之前我們在spring的主配置文件中要把spring的掃描組件啟動

<!-- spring組件掃描 -->
    <context:component-scan base-package="com.mxp">
    </context:component-scan>

dao

package com.mxp.jdbc.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.mxp.jdbc.entity.User;
import com.mxp.jdbc.entity.UserRowMapper;


@Repository
public class ItinerantDAO {
    @Autowired
    private JdbcTemplate template;//注入的方式
    public void save(User user){
        String sql = "insert into test_user" +
         "(id,user_name) values (?,?)";
        Object[] params = {
                 user.getId(),user.getUserName()
        };
        template.update(sql, params);
    }
    public List<User> findAll(){
        String sql ="select * from test_user";
        UserRowMapper rowMapper = new UserRowMapper();
        List<User> list = template.query(sql, rowMapper);
        return list;
    }
 
}

那現在就可以寫測試方法

package test;

import java.io.IOException;

import java.util.List;




import org.apache.ibatis.session.SqlSession;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


import com.mxp.ControllerQW;

import com.mxp.jdbc.dao.ItinerantDAO;
import com.mxp.jdbc.entity.User;
import com.mxp.mybatis.util.MybatisUtil;

public class Test {
    public static void main(String[] args) {
//spring的主配置文件名 String conf
= "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); User user = new User(); user.setId("1455"); user.setUserName("文森特"); dao.save(user); } @org.junit.Test public void test(){
String conf
= "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); List<User> list = dao.findAll(); for(User u:list){ System.out.println(u.getUserName()); } } }

這jdbcTemplate 見的次數很少 至今為止 還沒有見到用的 

Mybatis

原來在我們使用jdbc的問題

1 對數據庫的連接 使用時就創建連接,不使用就立即釋放,對數據庫進行頻繁連接開啟和關閉,造成數據庫的資源浪費,影響數據庫的性能;

解決辦法:使用數據庫連接池,管理數據庫的連接。

2 將sql語句硬編碼到java代碼中,如果sql語句修改,需要重新編譯java代碼,不利於系統維護,

解決辦法:把sql語句I定義到xml配置文件里;

3 在向statement中設置參數,對站位符位置和設置參數數值,硬編碼到java代碼中,

4 從result結果集中遍歷數據時,存在硬編碼,講獲取表的字段名硬編碼,不便於維護,

講結果集 自動映射成java對象

mybatis的架構

是一個持久層的項目,是阿帕奇的頂級項目,

通過 mybatis提供的映射方式,半自動的生成sql,大部分還是需要程序員編寫sql

核心:輸入映射:可以將statement中的輸入參數自動輸入到映射 通過ongl表達式,將查詢的結果集靈活映射成為java對象(輸出映射)

mybatis的結構
那么說一下myabtis的大致工作流程

1、  mybatis配置

SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。

2、  通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠

3、  由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行。

4、  mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。

5、  Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。

6、  Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過 Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。

7、  Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過 Mapped Statement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。

 
第一步主配置文件
<?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>
<environments default="environment">
        <environment id="environment">
            <transactionManager type="JDBC" />
            <!-- mybatis 自帶連接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&amp;characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <!-- 定義sqlMapper文件位置的 -->
    <mappers>
        <mapper resource="com/mxp/mybatis/entity/UserMapper.xml" />
    </mappers> 
</configuration>

第二步 實體類及其sqlmap映射文件

package com.mxp.mybatis.entity;

import java.io.Serializable;

public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String userName;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
}
<?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.mxp.mybatis.entity.UserMapper">
   
    <sql id="userColumns">
        a.id AS "id",
        a.user_name AS "userName"
    </sql>
    
    <select id="findAll" resultType="com.mxp.mybatis.entity.User" >
            SELECT <include refid="userColumns"/>
                FROM test_user a
    </select>
    
    <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" >
        SELECT <include refid="userColumns"/>
                FROM test_user a
                <where>
                    a.user_name like #{name}
                </where>
                 
    </select>
    
</mapper>

第三部 獲取sqlsession

package com.mxp.mybatis.util;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtil {
    
    public static SqlSession getInsertance(){
        SqlSessionFactoryBuilder builder = 
                new SqlSessionFactoryBuilder();
        //這是讀取文件后 形成一個輸入流 漲知識了
        //Test 其實就是一個類型 寫自己的什么類型都行 主要是為了獲取到getClassLoader().getResourceAsStream
        InputStream reader = MybatisUtil.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
        //獲取sqlsessionFactory
        SqlSessionFactory factory =  builder.build(reader);
        //獲取session
        SqlSession session = factory.openSession();
        return session;
    }

}

第四部 寫測試類

package test;

import java.io.IOException;

import java.util.List;




import org.apache.ibatis.session.SqlSession;
import com.mxp.mybatis.util.MybatisUtil;

public class Test {
  
    @org.junit.Test
    public void getSqllSession() throws IOException{
        
        SqlSession session = MybatisUtil.getInsertance();
        System.out.println("獲取session");
        session.close();
    }
    @org.junit.Test
    public void findall(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        List<com.mxp.mybatis.entity.User> list =  sqlsession.selectList("findAll");
        for(com.mxp.mybatis.entity.User u:list){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
        
    }
    @org.junit.Test
    public void findLike(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        List<com.mxp.mybatis.entity.User> list =  sqlsession.selectList("findLikeName","%文%");
        for(com.mxp.mybatis.entity.User u:list){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
        
    }
}

 Mybatis的

Mapper映射器接口規則,會自動生成接口實現類。

修飾public

a.根據sqlMapper定義的id屬性當接口方法名

b 根據sqlMapper定義的parameterType類型定義參數類型

c 根據sqlMapper定義的resultType的類型 定義方法的返回類型

(多行使用list<泛型(resultType的類型)>,單行使resultType的類型)

d 將sqlMapper的namespace屬性指定成為 包名.接口名字,就是接口的位置,

 如何取到接口實現類呢

從sqlsession中獲取

sqlsession.getMapper(接口的class對象);

mybatis替我生成實現類,在實現類中把sqlsession.select*的各種操作封裝起來

 首先實現 d

<?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.mxp.mybatis.dao.UserDao">
   
    <sql id="userColumns">
        a.id AS "id",
        a.user_name AS "userName"
    </sql>
    
    <select id="findAll" resultType="com.mxp.mybatis.entity.User" >
            SELECT <include refid="userColumns"/>
                FROM test_user a
    </select>
    
    <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" >
        SELECT <include refid="userColumns"/>
                FROM test_user a
                <where>
                    a.user_name like #{name}
                </where>
                 
    </select>
    
</mapper>

 a b c

package com.mxp.mybatis.dao;

import java.util.List;



import com.mxp.mybatis.entity.User;

public interface UserDao {
 public List<User> findAll();
 public List<User> findLikeName(String name);
}

測試生成的映射器接口實現類

@org.junit.Test
    public void testMapper(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        UserDao dao = sqlsession.getMapper(UserDao.class);
        List<com.mxp.mybatis.entity.User> os = dao.findAll();
        for(com.mxp.mybatis.entity.User u:os){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
    }

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM