一篇文章入門MyBatis3

要使用mybatis,需要在類路徑下建立一個配置文件,名稱爲mybatis-config.xml

mybatis中的總配置文件(mybatis-config.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>

<!-- environments在集成Spring後不用配置,environment 元素體中包含了事務管理和連接池的配置 -->
	<!--environments 的id可以隨意配置-->	
	<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/ssm_mybatis" />
				<property name="username" value="root" />
				<property name="password" value="123456789" />
				
			</dataSource>
		</environment>
	</environments>
	
	<!--用來關聯實體類,xml對應一個類-->
	<mappers>
		<mapper resource="mapper/UserMapper.xml" />
	</mappers>
</configuration>

mybatis中的Mapper.xml:

mybatis通過實體類訪問數據庫,實體類要符合JavaBean規範
實體類要對應一個mapper.xml,名稱隨意,最好是類名 + Mapper.xml
如下(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內部是寫sql語句的	
  -->
<mapper namespace="UserMapper">
	<!--select屬性:
	id:給sql語句命名,用來調用
	parameterType:傳入參數的類型(可選)
	resultType:返回值的類型(類路徑),即使有多個返回值,不用寫list類
	-->
	<select id="selectUserById" parameterType="Integer" resultType="model.User">
		<!--sql語句和原生的幾乎一樣,佔位符不再是?,而是#{},而且需要取名字,名字沒有要求-->
		select * from user where u_id = #{id}
	</select>
</mapper>

mybatisAPI以及基本查詢:

在類中使用mybatisAPI使用mybatis操作數據庫:

		//將mybatis的配置文件路徑保存爲String,在類路徑下可以直接保存名稱
		String resource = "mybatis-config.xml";
		
		//使用mybatis提供Resources讀取配置文件,獲取一個輸入流
		InputStream inputStream = Resources.getResourceAsStream(resource);
		
		//新建一個mybatis提供的sqlSessionFactoryBuilder
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		
		//利用創建的builder讀取輸入流的數據創建SessionFactory
		SqlSessionFactory factory = builder.build(inputStream);
		
		//利用工廠打開一個sqlSession
		SqlSession session = factory.openSession();
		
		//操作數據庫
		
//		參數1:要操作的SQL語句名稱,在實體類的mapper文件裏配置名稱,命名空間 + id
//		參數2:sql語句的傳入參數
//		查詢一條數據,通過id = 1
		User user = (User)session.selectOne("UserMapper.selectUserById", 1);
		


//		如果進行增刪改操作,則需要提交事務
//		session.commit();

mybatis其他數據庫操作方式:

模糊查詢:

///xml配置
//模糊查詢不能使用#{},需要使用${},名稱必須爲value,${}爲ognl表達式,可以用來字符串拼接
//如有需要,注意查詢前設置數據庫編碼爲utf8,否則無法顯示中文數據
<select id="selectUserByName" parameterType="String" resultType="model.User">
		select * from user where u_id like '%${value}%'
</select>

//java語句
//如果查詢結果爲多個,可以用selectList
List<User> list = session.selectList("UserMapper.selectUserByName", "王");

插入數據:

//xml配置
<insert id="insertUser" parameterType="model.User">
	//使用#{}可以獲取user實例中的字段,用法類似ognl表達式
	insert into user values(null, #{u_username},#{u_password},#{u_sex},#{u_createTime},#{u_cid});
</insert>

//java代碼
User user = new User("A","B","C",new Date(),1);//創建測試實例
session.insert("insertUser", user);
session.commit();

修改數據

//xml配置
<update id="updateUserName" parameterType="model.User">
	update user set u_username = #{u_username} where u_id = #{u_id};
</update>

//java代碼
User user = new User();
user.setU_id(1);//mybatis根據數據的id修改數據
session.update("updateUserName", user);
session.commit();

刪除數據

//xml配置
<delete id="deleteUser" parameterType="Integer">
	delete from user where u_id = #{id};
</delete>
//java代碼
session.delete("deleteUser", 1);
session.commit();	

創建MybatisUtils(獲取session):

package utils;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisUtils {
	
	private static SqlSessionFactory sessionFactory = null;
	private static InputStream inputStream = null;
	
	static {
		String resource = "mybatis-config.xml";
		
		try {
			inputStream = Resources.getResourceAsStream(resource);
		} catch (IOException e) {
			e.printStackTrace();
		}
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		sessionFactory = builder.build(inputStream);
	}
	
	public static SqlSession getSession(){
		return sessionFactory.openSession();
	}
	
}	

mybatis動態代理(官方推薦):

使用一個可以和mapper.xml文件映射的接口實現動態代理
通過接口可mapper實現Dao的功能,而不是自己寫Dao的實現類
UserMapper.xml

<mapper namespace="dao.UserMapper">
	<select id="selectUserById" parameterType="Integer"
		resultType="model.User">
		select * from user where u_id = #{id};
	</select>
</mapper>

UserMapper.java

public interface UserMapper {
	
	//mapper動態代理開發四大原則
	//1.接口方法名需要與mapper.xml的要調用的sql語句的id一致
	//2.接口的形參類型需要與mapper.xml parameterType一致
	//3.接口的返回值需要與mapper.xml resultType一致
	//4.mapper.xml中namespace要與接口的全包名一致
	
	public User selectUserById(Integer id);
	
}

動態方法調用:

//先使用getMapper獲取接口實例(接口實例由mybatis根據mapper幫助實現)
UserMapper mapper = session.getMapper(UserMapper.class);

//然後就可以直接調用方法
User user = mapper.selectUserById(1);

在mybatis中使用log輸出日誌:

在項目目錄下添加log4j.properties文件:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

%{}和#{}的區別:

#{}是佔位符,運行時替換爲‘參數’,帶有單引號
%{}時ognl表達式,可以用作字符串拼接,傳入參數不會添加單引號

mybatis中的properties屬性:

properties(讀取配置文件)
mybatis可以讀取properties文件中的數據:

<properties resource="db.properties"/>

然後可以使用${}讀取properties文件內容
通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的則是 properties 元素中指定的屬性。

mybatis中的typeAliases(類型別名):

類型別名可爲 Java 類型設置一個縮寫名字。 它僅用於 XML 配置,意在降低冗餘的全限定類名書寫。

推薦使用包的形式設置別名,如果Javabean的數量比較多的話,使用包的形式設置別名,包下的所有類使用只要使用類名即可
報的形式會掃描主包及自包下的所有文件,以對象類名爲別名,大小寫不限,推薦使用小寫

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

mybatis中的mappers(配置映射器的位置):

mappers時寫sql語句的地方
mappers可以使用絕對路徑(url),相對路徑(resource)、類名(class)、映射器
(name)定位,但由於都是單個配置,如果類多起來,比較麻煩,所以推薦使用包來配置:

<mappers>
	<package name="mapper"/>
</mappers>

使用包配置時,主要要將接口(動態調用)和xml文件都放在此包下

mybatis中的輸入輸出映射:

mybatis中的輸入映射:
parameterType:可以是基本數據類,包裝類(不僅僅時Integer、Double,還可以時List< User >,或者是自定義的包裝類),自定義類,

mybaits中的輸出映射:
可以這樣理解:
mybatis從數據庫中查找數據,查出的數據是一張表,第一行是各個屬性名稱,以下每一行都是一條記錄,每條記錄都可以轉化爲一個對象,那麼如何轉化爲對象?設置resultType提供一個類名,讓mybatis自己判斷如何構造對象:
resultType:
首先根據提供的類構造一個對象,然後再逐一掃描result表每一行記錄,每條記錄從左到右掃描,如果如果掃描位置有值,如果bean類中有對應名稱的setter方法,則用setter方法設置到對象中,否則跳過。
resultMap: 如果指定的是resultMap,則在每個記錄注意掃描時去resultMap中檢查是否存在該名稱的映射,如果有,則按照設置的映射關係映射,如果沒有則按照resultType的規則映射。

resultType和resultMap不能共用,只能用其中的一個

什麼時候使用哪個?
resultType(自動映射,如果是實體類,需要實體類中的屬性和數據庫中的表完全一致纔可以使用):可以是基本類型、自定義對象或是集合
resultMap(手動映射,實體類中的屬性可以不和數據庫中的列完全一致命名):bean中的屬性值和數據庫中的列不匹配
手動映射(例子):

<!---->
<!--resultMap屬性:
	type:類型,就是映射bean類
	id:由於resultMap單獨設置在查詢標籤外,所以需要用id來找到該resultMap標籤
	result:可以理解爲鍵值對映射
		-property:bean類中和數據庫列名不一致的但對應的那個屬性
		-column:數據庫中和bean屬性不一致但是對應的那一類
-->
<resultMap type="Country" id="country">
	<result property="id" column="c_id"/>
</resultMap>

<!--然後使用select標籤時設置resultMap屬性爲上述id,就可以了-->
<select id="selectAll" resultMap="country">
	select * from country;
</select>
<!--沒有設置的屬性則會自動映射(需要屬性名和數據庫列名一致)-->

mybatis的關聯查詢:

在mybatis中設置關聯的作用(個人理解):
其實使用sql進行多表查詢已經不是問題,使用各種連接,只要有數據,都不是問題。問題是如何把這些數據封裝成一個個對象方便操作呢?我們需要一個能夠能承載查詢信息的類,毫無疑問就是實體類,怎樣把數據放到實體類中?這裏需要使用resultMap(mybatis多表查詢不能用resultType)
假如有一個用戶類和一個國家類,則一個用戶對一個國家,一個國家對多個用戶。

示例:
一個用戶對一個國家(一對一):

<!---->

<resultMap type="User" id="userinfo">
	<!--使用多表查詢時,只有手動配置的屬性纔會被查詢,沒有手動配置的屬性不會獲取-->
	<!--使用id標識主鍵,使用result標識普通屬性,可以混用,但是最好區別開-->
	<id property="u_id" column="u_id" />
	<result property="u_username" column="u_username" />
	<result property="u_sex" column="u_sex" />
	<result property="u_cid" column="u_cid" />

<!--association用來接收一對一的另一個表的信息(國安):
	property:接受類中另一個類的引用名稱
	javaType:另一個類的類型
	
	-->
	<association property="country" javaType="Country">
		<result property="c_countryname" column="c_countryname"/>
		<result property="c_capital" column="c_capital"/>
	</association>

</resultMap>
<select id="selectUserInfoOnetoOne" 
	resultMap="userinfo">
	select
	u_id,u_username,u_sex,u_cid,c_countryname,c_capital
	from user u
	left join
	country c
	on
	u.`u_id` = c.`c_id`;
</select>

(一個國家對多個用戶)一對多:

<!---->
<resultMap type="Country" id="countryuser">
	<id property="c_id" column="c_id" />
	<id property="c_countryname" column="c_countryname" />
	<id property="c_capital" column="c_capital" />

<!--collection 屬性:
	property:接受類中的另一個類的集合引用
	ofType:集合類範型類型
	
-->
	<collection property="userLists" ofType="User">
		<result property="u_username" column="u_username"/>
		<result property="u_sex" column="u_sex"/>
	</collection>
</resultMap>
<select id="selectCountryUserManytoOne" resultMap="countryuser">
	select
	c_id,c_countryname,c_capital,u_username,u_sex
	from
	country c
	left join
	user u
	on
	u.`u_cid` = c.`c_id`;
</select>

mybatis動態sql:方便拼接sql語句

if標籤:
在mybatis的sql語句中,可以使用if標籤根據參數是否存在執行不同的sql語句:

<!---->
<select id="selectUserUseIf" resultType="User" parameterType="User">
	select u_id,
	<!--test後面跟上條件,獲取傳入的值不需要加上#{}-->
	<if test="u_username!=null">
		u_username,
	</if>
	u_sex from user;
</select>

但是拼接的sql語句中有and關鍵字時容易出現問題:

<!---->
<!--如果u_sex== null,sql語句and就會直接連接在where後面,着顯然是錯的-->
<select id="selectUserUseIf" resultType="User" parameterType="User">
	select * from user where
	<if test="u_sex!=null and u_sex!=''">
	u_sex = #{u_sex}
	</if>
	<if test="u_cid!=null">
	and u_cid = #{u_cid}
	</if>
</select>

mybatis提供了where標籤解決這個問題,如果子句的開頭是and,where會把它去掉,where標籤默認前綴會生成where關鍵字
where標籤:
解決if標籤拼接字符串and符號問題

<select id="selectUserUseIf" resultType="User"
	parameterType="User">	
		select * from user
		<where>
		<if test="u_sex!=null and u_sex!=''">
			u_sex = #{u_sex}
		</if>
		<if test="u_cid!=null">
			AND u_cid = #{u_cid}
		</if>
	</where>
</select>

trim標籤:
可以定製where標籤的規則:

<!--示例-->
<!--
prefix:可以在運行時替換<trim>爲a
suffix:可以在運行時替換</trim>爲b
prefixOverrides:如果子句前綴爲c,可以在必要時自動去除,可以使用 | 分隔多個選項
suffixOverrides:如果子句後綴爲c,可以在必要時自動去除,可以使用 | 分隔多個選項
-->
<trim prefix="a" suffix="b" prefixOverrides="c" suffixOverrides="d">
</trim>

set標籤:
解決拼接字符串時逗號問題
set標籤用來替代手寫的set關鍵字,可以在必要時去掉子句末尾的逗號,用法和where標籤類似。

foreach標籤:
如果sql使用in,可以用該標籤動態生成數組:

<!---->
<select id="selectUserUserIn" resultType="User">
	select * from user u where u.`u_id` in 
	<!--如果傳入的是List類型,則collection的值爲list,如果是數組類型,則爲array,如果時包裝類,直接寫引用名稱-->
	<!--foreach屬性:
		item:數組或集合的迭代值
		separator:每兩個迭代值中的分隔符
		open:迭代開始時插入符號
		close:迭代結束時插入符號
	-->
	<foreach collection="array" item="num" separator="," open="(" close=")">
		#{num}
	</foreach>
</select>

sql標籤:
可以提取重複sql重用:

<!---->
<!--設置sql語句-->
<sql id="selectuser">
	select * from user u 
</sql>
<!--使用-->
<include refid="selectuser"></include>

mybatis中的Generator(MBG)

作用:根據數據庫表自動自動生成Bean對象,java接口及SqlMapper.xml配置文件:
Generator的配置
generatorConfig.xml):
放在src目錄下

<?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爲主要配置標籤, targetRuntime爲運行環境 -->
	<context id="MyGenerator" targetRuntime="MyBatis3">


		<!-- 可以讓生成的代碼簡潔一點 -->
		<commentGenerator>
			<!-- 去掉註釋 -->
			<property name="suppressAllComments" value="true" />
			<!-- 去掉時間戳 -->
			<property name="suppressDate" value="true" />

		</commentGenerator>


		<!-- 數據庫連接信息,配置連接數據庫的必要信息 -->
		<jdbcConnection 
			driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost/ssm_mybatis"
			userId="root"
			password="123456789">
		</jdbcConnection>

		<!-- javajdbc數據類型轉換規則 ,設置爲false則使用默認配置-->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- javaModelGenerator:javabean配置 
		targetPackage:輸出包名 
		targetProject:輸出項目位置 -->
		<javaModelGenerator targetPackage="com.echo.bean"
			targetProject="src">
			
			<!--enableSubPackages:是否開啓子包名稱 是否在包名後面架上scheme名稱 -->
			<property name="enableSubPackages" value="false" />
			
			<!-- 在setter方法中加入trim,去掉空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<!-- mapper.xml配置,屬性作用同上-->
		<sqlMapGenerator targetPackage="com.echo.mapper"
			targetProject="src">
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>


		<!-- java接口的配置,屬性作用同上,type設置生成的文件類型爲XML -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.echo.mapper" targetProject="src">
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>

		<!-- 數據表 要根據數據庫中的表來生成,tableName:數據庫中表的名稱 -->
		<table tableName="user"></table>
		<table tableName="country"></table>

	</context>
</generatorConfiguration>

調用配置文件(官方給出的代碼,複製即可):

List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("src/generatorConfig.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);

在實體類的目錄下會生成實體類的example類,其中封裝了許多查詢方式如:insert(完全插入數據)、insertSelective(帶有判斷的插入數據項)…
示例:
查詢創建時間爲null且姓名帶有"老"的用戶(selectByExample)

package test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.echo.bean.User;
import com.echo.bean.UserExample;
import com.echo.mapper.UserMapper;

import utils.MybatisUtils;

public class Test {
	public static void main(String[] args) {
		SqlSession session = MybatisUtils.getSession();
		UserMapper mapper = session.getMapper(UserMapper.class);
		UserExample userExample = new UserExample();
		
		//在createCriteria()下可以創建多種選擇規則,且方法名稱易於理解
		userExample.createCriteria().andUCreatetimeIsNull().andUUsernameLike("%老%");
	
		//直接將設置好條件的UserExample 示例傳入方法selectByExample即可完成查詢
		List<User> list = mapper.selectByExample(userExample);
		for(User u:list) {
			System.out.println(u);
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章