1. 程式人生 > >Mybatis 入門案例分享

Mybatis 入門案例分享

java mybatis


本文分享一下,Mybatis的一些入門案例;


為什麽不用JDBC方式來操作數據庫,而使用類似於Mybatis的框架呢?


1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。

解決:SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。

2、 Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

解決:Sql語句配置在XXXXmapper.xml文件中與java代碼分離。

3、 sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應。

解決:

Mybatis自動將java對象映射至sql語句,通過statement中的parameterType定義輸入參數的類型。

4、 對結果集解析麻煩,sql變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。

解決:Mybatis自動將sql執行結果映射至java對象,通過statement中的resultType定義輸出結果的類型。


一、需求:

根據用戶id查詢一個用戶信息

根據用戶名稱模糊查詢用戶信息列表

添加用戶

更新用戶

刪除用戶


二、環境搭建

第一、創建maven工程,添加mybatis依賴、mysql驅動等依賴,pom文件如下;

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.xingej.mybatis</groupId>
	<artifactId>itcast-mybatis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>itcast-mybatis</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>

		<!-- 數據庫驅動 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.39</version>
		</dependency>

		<!-- mybatis依賴 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.5</version>
		</dependency>
		
		<!-- log4j 日誌依賴 -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>



	</dependencies>
</project>


第二、添加SqlMapConfig.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>
	<!-- 和spring整合後 environments配置將廢除-->
	<environments default="development">
		<environment id="development">
		<!-- 使用jdbc事務管理-->
			<transactionManager type="JDBC" />
		<!-- 數據庫連接池-->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<mapper resource="sqlMap/User.xml"/>
	</mappers>
	
</configuration>


第三、創建po類

package com.xingej.mybatis.po;

import java.util.Date;

/**
 * po類,就是屬性+get/set方法
 * 
 * @author erjun
 *
 */
public class User {
    private int id;

    private String username;// 用戶姓名

    private String sex;// 性別

    private Date birthday;// 生日

    private String address;// 地址

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                + address + "]";
    }

}


第四、編寫po類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命名空間,為了對sql語句進行隔離,方便管理 ,mapper開發dao方式,使用namespace有特殊作用 -->
<mapper namespace="test">
<!-- 在mapper.xml文件中配置很多的sql語句,執行每個sql語句時,封裝為MappedStatement對象
mapper.xml以statement為單位管理sql語句
 -->

	<!-- 根據id查詢用戶信息 -->
	<!-- 
		id:唯一標識 一個statement
		#{}:表示 一個占位符,如果#{}中傳入簡單類型的參數,#{}中的名稱隨意
		parameterType:輸入 參數的類型,通過#{}接收parameterType輸入 的參數
		resultType:輸出結果 類型,不管返回是多條還是單條,指定單條記錄映射的pojo類型
	 -->
	<select id="findUserById" parameterType="int" resultType="com.xingej.mybatis.po.User">
		SELECT * FROM USER WHERE id= #{id}
	
	</select>
	
	<!-- 根據用戶名稱查詢用戶信息,可能返回多條
	${}:表示sql的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在sql中。
		${}方式的缺點:不能防止sql的註入;select * from user where name like ‘xiaoming‘ or ‘1=1‘
		這條語句,始終成立,後面的‘ or ‘1=    就是sql註入;
		有的時候,軟件在交付的時候,會進行sql註入的校驗。
	 -->
	<select id="findUserByName" parameterType="java.lang.String" resultType="com.xingej.mybatis.po.User">
		select * from user where username like ‘%${value}%‘
	</select>
	
	<!-- 添加用戶
	parameterType:輸入 參數的類型,User對象 包括 username,birthday,sex,address
	#{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
	#{username}表示從parameterType中獲取pojo的屬性值
	selectKey:用於進行主鍵返回,定義了獲取主鍵值的sql
	order:設置selectKey中sql執行的順序,相對於insert語句來說
	keyProperty:將主鍵值設置到哪個屬性
	resultType:select LAST_INSERT_ID()的結果 類型
	
	 -->
	<insert id="insertUser" parameterType="com.xingej.mybatis.po.User">
		<selectKey keyProperty="id" order="AFTER" resultType="int">
			select LAST_INSERT_ID()
		</selectKey>
		
		INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
	</insert>
	
	<!-- mysql的uuid生成主鍵 -->
	<!-- <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		<selectKey keyProperty="id" order="BEFORE" resultType="string">
			select uuid()
		</selectKey>
		
		INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
	</insert> -->
	
	<!-- oracle
	在執行insert之前執行select 序列.nextval() from dual取出序列最大值,將值設置到user對象 的id屬性
	 -->
	<!-- <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		<selectKey keyProperty="id" order="BEFORE" resultType="int">
			select 序列.nextval() from dual
		</selectKey>
		
		INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
	</insert> -->
	
	<!-- 用戶刪除  -->
	<delete id="deleteUser" parameterType="int">
	 delete from user where id=#{id}
	</delete>
	<!-- 用戶更新 
	要求:傳入的user對象中包括 id屬性值
	-->
	<update id="updateUser" parameterType="com.xingej.mybatis.po.User">
		update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
	</update>

</mapper>


補充說明:

技術分享



三、編寫測試用例


package com.xingej.mybatis.first;

import java.io.IOException;
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 com.xingej.mybatis.po.User;

public class MybatisFirst {
    // 聲明一個全局的會話工廠
    SqlSessionFactory sqlSessionFactory = null;

    // 創建session工廠
    @Before
    public void init() throws IOException {
        // 1、配置文件(SqlMapConfig.xml)
        String resource = "SqlMapConfig.xml";
        // 2、加載配置文件,轉換成流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 3、創建會話工廠SessionFactory

        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }

    // 根據用戶ID查詢用戶(得到單條記錄)
    @Test
    public void testFindUserById() {
        // 1、通過session工廠來創建一個session
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 2、通過session會話來操作數據庫
        // 第一個參數:statement位置:就是namespace + statement的id
        // 第2個參數:就是你傳入的參數
        User user = null;

        try {
            user = sqlSession.selectOne("test.findUserById", 1);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

        System.out.println("----user-----:\t" + user);
    }

    // 根據用戶名稱來查詢,
    // 返回結果是List類型
    // 支持模糊查詢
    @Test
    public void testFindUserByName() {
        // 1、獲取session會話
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 2、操作數據庫
        List<User> users = null;
        try {
            users = sqlSession.selectList("test.findUserByName", "小明");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

        System.out.println("----->:\t" + users.get(2).getUsername());
    }

    // 插入一條記錄
    @Test
    public void testInsertUser() {
        // 1、通過session工廠來創建一個session
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 2、通過session會話來操作數據庫
        User user = new User();
        user.setAddress("北京");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setUsername("浪子燕青");

        try {
            sqlSession.insert("test.insertUser", user);
            // 提交事務,千萬別忘記
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

        System.out.println("----user-----:\t" + user);
    }

    // 更新一條記錄
    @Test
    public void testUpdateUser() {
        // 1、通過session工廠來創建一個session
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 2、通過session會話來操作數據庫
        User user = new User();
        user.setId(16);
        user.setAddress("北京");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setUsername("故、新");

        try {
            sqlSession.update("test.updateUser", user);
            // 提交事務,千萬別忘記
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

        System.out.println("----user-----:\t" + user);
    }

    // 刪除一條記錄
    @Test
    public void testDeleteUser() {
        // 1、通過session工廠來創建一個session
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 2、通過session會話來操作數據庫
        try {
            sqlSession.update("test.deleteUser", 26);
            // 提交事務,千萬別忘記
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

    }

}



總結:

1、SqlMapConfig.xml 文件

mybatis全局配置文件,只有一個,名稱不固定的,主要mapper.xmlmapper.xml中配置 sql語句

2、mapper.xml文件

mapper.xml是以statement為單位進行配置。(把一個sql稱為一個statement),satatement中配置 sql語句、parameterType輸入參數類型(完成輸入映射)、resultType輸出結果類型(完成輸出映射)。

還提供了parameterMap配置輸入參數類型(過期了,不推薦使用了)

還提供resultMap配置輸出結果類型(完成輸出映射),通過resultMap完成復雜數據類型的映射(一對多,多對多映射)

3、#{} 符號說明:

表示一個占位符,向占位符輸入參數,mybatis自動進行java類型和jdbc類型的轉換。

程序員不需要考慮參數的類型,比如:傳入字符串,mybatis最終拼接好的sql就是參數兩邊加單引號。

#{}接收pojo數據,可以使用OGNL解析出pojo的屬性值

4、${} 符號說明:

表示sql的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在sql中。

${}也可以接收pojo數據,可以使用OGNL解析出pojo的屬性值

缺點:不能防止sql註入。

例如:select * from user where name like ‘xiaoming‘ or ‘1=1‘

這條語句,始終成立,後面的 ‘ or ‘1= 就是sql註入


代碼已經上傳到git上:

https://github.com/xej520/xingej-mybatis





本文出自 “XEJ分布式工作室” 博客,請務必保留此出處http://xingej.blog.51cto.com/7912529/1979119

Mybatis 入門案例分享