JAVA 框架-Mybatis
一.Mybatis簡介
1.MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github。
iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAOs)。
2.功能架構:
(1)API接口層:提供給外部使用的接口API,開發人員通過這些本地API來操縱數據庫。接口層一接收到調用請求就會調用數據處理層來完成具體的數據處理。
(2)數據處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次數據庫操作。
(3)基礎支撐層:負責最基礎的功能支撐,包括連接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來作為最基礎的組件。為上層的數據處理層提供最基礎的支撐。
二.項目實例
需要導入的包:ojdbc6.jar(訪問數據庫必備的包)、mybatis-3.4.6.jar(Mybatis框架包)、log4j-1.2.17.jar(用於控制臺調試的工具包)
需要的文件:log4j.properties(調試模板)
配置Mybatis的總配置文件:
<?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="conf/db.properties"></properties><!-- 加載屬性文件,也可以直接定義屬性值 --> <typeAliases><!-- 別名類型,這樣寫默認以該包下類名為別名 --> <package name="com.hanqi.model"/> <!-- <typeAlias type="com.hanqi.model.House" alias="hhh"/>按照自己起的別名 --> </typeAliases> <environments default="development"><!-- 配置mybatis的運行環境 ,一般環境有3個,設置默認為開發環境--> <environment id="development"><!-- 開發環境 --> <!-- 配置事務管理器, 有兩種方式: 1, JDBC 2, MANAGED(拖管, 一般的商業服務器才會有這個功能, 比如JBOSS,Weblogic, tomcat沒有) --> <transactionManager type="JDBC"/><!-- 配置事物管理器類型 --> <!-- 數據源 type參數有三種: UNPOOLED, POOLED, JNDI UNPOOLED: 沒有連接池, 使用最普通的連接, 每次調用數據庫mybatis都會創建一個新的連接, 用完之後關閉, 適合小並發項目(並發: 用戶訪問量的意思) POOLED: 使用連接池, 創建若幹個連接, 用完之後放回連接池 JNDI: 使用應用服務器配置JNDI數據源獲取數據庫連接 --> <dataSource type="POOLED"><!-- 基於連接池的數據源,使用連接池可避免重復與數據庫進行連接 --> <property name="driver" value="${jdbc.classname}"/><!-- 配置連接數據庫的4個屬性 --> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers><!-- 配置映射文件路徑,加載映射文件 --> <mapper resource="mapper/*.xml"/> <!-- 如果使用<package>來掃描包中的映射文件, 則必須使用sqlSession.getMapper(接口.class)來定義方法 並且xml映射文件的名字必須跟接口的名字一樣 因為<package>掃描的不是xml的映射文件, 而是掃描的.java文件 --> </mappers> </configuration>
連接數據庫屬性文件:
jdbc.username=test0315 jdbc.password=123456 jdbc.url=jdbc:oracle:thin:@localhost:1521:xe jdbc.classname=oracle.jdbc.OracleDriver
構建sqlSession:
package util; 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; /* * 1, 構建SqlSessionFactory InputStream in = Resources.getResourceAsStream("總配置文件所在的src下的路徑"); SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in); 2, 構建SqlSession(註意SqlSession不能以一個class成員變量的身份被返回) SqlSession ss = ssf.openSession(); 3, 直接運行 a: 直接運行映射文件中的sql語句 ss.select... ss.insert... ss.update... ss.delete... b: 使用接口映射配置文件 ss.getMapper(接口類名.class); 調用接口的方法 * */ public class MyBatisUtil { public static SqlSession getSqlSession() { return getSqlSessionFactory().openSession();//構建SqlSession實例 } public static void main(String[] args) { System.out.println(getSqlSession()); } public static SqlSessionFactory getSqlSessionFactory() { String resource = "conf/mybatis-config.xml";//總配置文件路徑名 InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource);//使用輸入流讀取配置文件 } catch (IOException e) { e.printStackTrace(); } //構建SqlSessionFactory的實例 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return sqlSessionFactory; }
實體model層:
package com.hanqi.model; import java.util.Date; import java.util.List; //@Alias(value="ccc")//也可以通過在實體類上用註解起別名,優先於其他配置 public class Appuser { private Integer ids; private String uname; private String pword; private String realname; private Date createtime; private Integer mark; private Integer sex; private List<Accounts> accounts; public Integer getIds() { return ids; } public void setIds(Integer ids) { this.ids = ids; } //以下省略
package com.hanqi.model; import java.util.Date; import java.util.List; //@Alias(value="ccc")//也可以通過在實體類上用註解起別名,優先於其他配置 public class Appuser { private Integer ids; private String uname; private String pword; private String realname; private Date createtime; private Integer mark; private Integer sex; private List<Accounts> accounts; public Integer getIds() { return ids; } public void setIds(Integer ids) { this.ids = ids; } //以下省略
接口層:
package com.hanqi.dao; import java.util.List; import com.hanqi.model.Accounts; public interface AccountsDao { int insertAccounts(Accounts accounts); List<Accounts> selectAccounts(); int deleteAccountsByUserId(Integer ids); }
package com.hanqi.dao; import java.util.List; import java.util.Map; import com.hanqi.model.Appuser; public interface AppuserDao { int insertAppuser(Appuser appuser); int updateAppuserByUname(Appuser appuser); List<Appuser> selectAppuserBySex(Integer sex); int deleteAppuserByIds(Integer ids); List<Appuser> selectAppuserByParams(Map map); }
數據訪問映射文件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="com.hanqi.dao.AppuserDao"><!-- 配置每個實體類的映射文件/接口全路徑名 --> <sql id="Appuser"><!-- 配置sql語句 --> ids,uname,pword,realname,createtime,mark,sex </sql> <!-- 動態添加數據操作,傳遞參數時,#{}中寫的是Map集合中的鍵或者是實體類中的成員變量名--> <!-- 需要進行數據類型聲明,否則如果為null時無法放入數據庫中的,報錯 --> <insert id="insertAppuser" parameterType="Appuser" ><!-- 被調用的id/方法名,結果類型為實體類 --> <!--selectKey用於獲取添加後數據的主鍵,oracle不支持自增,用BEFORE,需要通過getIds方法獲取主鍵--> <selectKey keyProperty="ids" order="BEFORE" resultType="Integer" keyColumn="ids"> select sq_test.nextval ids from dual<!--dual是指偽列 --> </selectKey> insert into appuser( <include refid="Appuser"></include> ) values( #{ids}, #{uname,jdbcType = VARCHAR}, #{pword,jdbcType = VARCHAR}, #{realname,jdbcType = VARCHAR}, sysdate, 1, #{sex,jdbcType = DECIMAL}) </insert> <!-- 通過條件進行修改操作 --> <update id="updateAppuserByUname" parameterType="Appuser"><!-- 參數類型為實體類 --> update appuser <set>pword = #{pword},</set> <where>and uname = #{uname}</where> </update> <!-- 通過性別條件進行一對多聯合查詢 --> <resultMap type="Appuser" id="appuserList"> <id property="ids" column="IDS" /> <collection property="accounts" column="IDS" select="com.hanqi.dao.AccountsDao.selectAccountsByUserId"></collection> </resultMap> <select id="selectAppuserBySex" resultMap="appuserList" parameterType="Integer"> select * from appuser where sex = #{sex} </select> <!--通過id查詢結果--> <!--mybatis會自動將查詢結果的列名與實體類的成員變量名相匹配,如果一樣則調用set方法放進去 --> <select id="selectAppuserByIds" parameterType="Integer" resultType="Appuser"> select * from appuser where ids = #{ids} </select> <!--通過id條件進行邏輯刪除--> <update id="deleteAppuserByIds" parameterType="Integer"> update appuser set mark = 0 where ids = #{ids} </update> <!--通過參數進行查詢--> <select id="selectAppuserByParams" parameterType="Map" resultType="Appuser"> select <include refid="Appuser"></include> from appuser <where> <if test="sex != null"> and sex=#{sex} </if> <if test="plist != null"> and ids in <foreach collection="plist" item="ids" open="(" close=")" separator=","> #{ids} </foreach> </if> </where> </select> </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"> <mapper namespace="com.hanqi.dao.AccountsDao"> <insert id="insertAccounts" parameterType="Accounts" > insert into accounts <trim prefix="(" suffix=")" suffixOverrides=","><!--trim用法 --> ids, <if test="acco != null"> acco, </if> <if test="passwords != null"> passwords, </if> <if test="tel != null"> tel, </if> <if test="email != null"> email, </if> <if test="ptail != null"> ptail, </if> <if test="userid != null"> userid, </if> regtime, <if test="note != null"> note, </if> mark, </trim> <trim prefix="values(" suffix=")" suffixOverrides=","> sq_test.nextval, <if test="acco != null"> #{acco}, </if> <if test="passwords != null"> #{passwords}, </if> <if test="tel != null"> #{tel}, </if> <if test="email != null"> #{email}, </if> <if test="ptail != null"> #{ptail}, </if> <if test="userid != null"> #{userid}, </if> sysdate, <if test="note != null"> #{note}, </if> 1, </trim> </insert> <!-- 通過id查詢操作 --> <select id="selectAccountsByUserId" parameterType="Integer" resultType="Accounts"> select * from accounts where userid = #{userid} </select> <!-- 一對一查詢第一種方法 --> <!-- <resultMap type="Accounts" id="accountslist">結果集定義為實體類 <id column="IDS" property="ids"/>id用來記錄主鍵,column是取該列名下的值並賦值給實體類的成員變量中; <result column="ACCO" property="acco"/> <result column="PASSWORDS" property="passwords"/> <result column="TEL" property="tel"/> <result column="EMAIL" property="email"/> <result column="PTAIL" property="ptail"/> <result column="REGTIME" property="regtime"/> <result column="NOTE" property="note"/> <result column="UNAME" property="appuser.uname"/> <result column="PWORD" property="appuser.pword"/> </resultMap> <select id="selectAccounts" resultMap="accountslist">id指接口中的方法,resultMap指定義好的集合 select * from accounts ac,appuser ap where ac.userid = ap.ids </select> --> <!-- 第二種方法,對象級聯 --> <resultMap type="Accounts" id="accountslist"> <association property="appuser" column="USERID" select="com.hanqi.dao.AppuserDao.selectAppuserByIds"></association> </resultMap> <!--一對一聯合查詢--> <select id="selectAccounts" resultMap="accountslist"> select * from accounts </select> <!--通過條件邏輯刪除--> <update id="deleteAccountsByUserId" parameterType="Integer"> update accounts set mark = 0 where userid = #{userid} </update> </mapper>
測試類:
package test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.session.SqlSession; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.hanqi.dao.AccountsDao; import com.hanqi.dao.AppuserDao; import com.hanqi.model.Accounts; import com.hanqi.model.Appuser; import util.MyBatisUtil; public class JunitTest { private SqlSession sqlSession; private AppuserDao appuserDao; private AccountsDao accountsDao; @BeforeEach void setUp() throws Exception { sqlSession = MyBatisUtil.getSqlSession(); appuserDao = sqlSession.getMapper(AppuserDao.class); accountsDao = sqlSession.getMapper(AccountsDao.class); } @AfterEach void tearDown() throws Exception { sqlSession.commit(); sqlSession.close(); } @Test void test() { //添加操作 Appuser appuser = new Appuser(); appuser.setUname("小明1"); appuser.setPword("112345"); //appuser.setRealname("王五"); appuser.setSex(2); int r = appuserDao.insertAppuser(appuser); System.out.println(appuser.getIds()); System.out.println(r); //多參數查詢操作 Map map1 = new HashMap<>(); List<Integer> list1 = new ArrayList<>(); list1.add(361); list1.add(442); list1.add(495); map1.put("sex", 2); map1.put("plist", list1); List<Appuser> list = appuserDao.selectAppuserByParams(map1); p(list); } private void p(List<Appuser> list) { for(Appuser a:list) { System.out.println(a); } } void test1() { //修改操作 Appuser appuser = new Appuser(); appuser.setPword("hq1111"); appuser.setUname("admin"); int a = appuserDao.updateAppuserByUname(appuser); System.out.println(a); //邏輯刪除操作 appuserDao.deleteAppuserByIds(361); accountsDao.deleteAccountsByUserId(61); } }
特殊符號表達式:
< < 小於號
> > 大於號
& & 和
' ’ 單引號
" " 雙引號
例: select * from emp where sal < #{sal}
<![CDATA[]]>交由下一級去處理,即數據庫。
例:<![CDATA[select * from emp where sal < #{sal}]]>
JAVA 框架-Mybatis