iBatis從3.x開始改名爲MyBatis。除了Java之外,還有可用於.Net的Mybatis.Nethtml
相關依賴包(maven)java
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.7</version> </dependency>
映射相關文件自動生成(mybatis-generator)mysql
iBatis提供了Abator用於生成映射相關文件。Mybatis能夠用mybatis generator實現相似功能。web
mybatis默認使用的路徑和文件名(無需配置):src/main/resources/generatorConfig.xml算法
<?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> <!-- classPathEntry:數據庫的JDBC驅動--> <classPathEntry location="target\assist\WEB-INF\lib\mysql-connector-java-5.1.32.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 去除自動生成的註釋 --> <commentGenerator> <property name="suppressAllComments" value="true"/> <property name="suppressDate" value="true"/> </commentGenerator> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testdb?autoReconnect=true" userId="xxxx" password="xxxxx"/> <!-- 生成Model類,targetProject:自動生成代碼的位置 --> <javaModelGenerator targetPackage="com.demo.models" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- 生成XML映射文件 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 生成Mapper接口(DAO) --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.demo.mappers" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 經過javaTypeResolver元素控制類型轉化,也能繼承JavaTypeResolver接口實現本身的類型轉換器。 --> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> <!--將 JDBC DECIMAL和NUMERIC解析爲Integer,而不是BigDecimal--> </javaTypeResolver> <!-- 要生成映射代碼的數據表,tableName爲表名;domainObjectName爲對應的javaBean類名, enablexxxxx是與Example類相關的配置 --> <table tableName="person" domainObjectName="Person"/> <table tableName="my_table" domainObjectName="myTable" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> <!--<columnRenamingRule searchString="^D_" replaceString=""/> <property name="useActualColumnNames" value="false"/> --> </table> ...... </context> </generatorConfiguration>
generatorConfig.properties文件spring
# 數據庫驅動jar 路徑 driver.class.path=target/assist/WEB-INF/lib/mysql-connector-java-5.1.32.jar # 數據庫鏈接參數 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf-8 jdbc.username=uname jdbc.password=pwd # 包路徑配置 model.package=com.demo.modules.entity dao.package=com.demo.modules.mapper xml.mapper.package=com.demo.modules.mapper target.project=src/main/java
<?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> <properties url="${mybatis.generator.generatorConfig.properties}"> <!--maven pom文件properties中配置的屬性--> <classPathEntry location="${driver.class.path}"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/> <!-- 生成Model類,targetProject:自動生成代碼的位置 --> <javaModelGenerator targetPackage="${model.package}" targetProject="${target.project}"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> ...... </context> </generatorConfiguration>
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <!-- 省缺值爲:src/main/resources/generatorConfig.xml <configurationFile>src/main/resources/mybatis-generator/generatorConfig.xml</configurationFile>--> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <executions> <execution> <id>Generate MyBatis Artifacts</id> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
mvn mybatis-generator:generate mvn mybatis-generator:generate -Dmybatis.generator.overwrite=true
使用mybatis-generator-core-xxxx.jar包sql
java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite
http://blog.csdn.net/lele2426/article/details/38794399 數據庫
生成的model類是普通的java類,包含與數據庫表各個字段對應的屬性極其setter和getter方法。express
http://openwares.net/database/mybatis_generator_example.htmlapache
Example類用於構造複雜的篩選條件。
Criterion
Criterion是最基本,最底層的Where條件,用於字段級的篩選。主要有如下這些:
LIKE模糊查詢的%,?字符只能在構造查詢條件是手動指定。
Mybatis Generator會爲每一個字段生成如上所示的Criterion,理論上能夠構造任何篩選條件,若是字段較多生成的Example類會很大。
Criteria
Criteria包含了Cretiron的集合,同一個Criteria中的各個Cretiron之間爲邏輯與(AND)關係。
oredCriteria
Example內有一個成員叫oredCriteria,是Criteria的集合,集合中的各個Criteria直接爲邏輯或(OR)的關係。
用法
http://mybatis.org/generator/generatedobjects/exampleClassUsage.html
TestTableExample example = new TestTableExample(); example.or() .andField1EqualTo(5) .andField2IsNull(); example.or() .andField3NotEqualTo(9) .andField4IsNotNull(); List<Integer> field5Values = new ArrayList<Integer>(); field5Values.add(8); field5Values.add(11); field5Values.add(14); field5Values.add(22); example.or() .andField5In(field5Values); example.or() .andField6Between(3, 7);
產生的SQL語句以下:
where (field1 = 5 and field2 is null) or (field3 <> 9 and field4 is not null) or (field5 in (8, 11, 14, 22)) or (field6 between 3 and 7)
sql語句映射配置文件。
<?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.demo.mappers.PersonMapper"> <resultMap id="BaseResultMap" type="com.demo.models.Person"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> ...... </resultMap> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.demo.models.Person"> <result column="content" jdbcType="LONGVARCHAR" property="content" /> </resultMap> <sql id="Update_By_Example_Where_Clause"> <where> <foreach collection="example.oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Base_Column_List"> id, name </sql> <sql id="Blob_Column_List"> content </sql> <select id="selectByExampleWithBLOBs" parameterType="com.demos.models.PersonExample" resultMap="ResultMapWithBLOBs"> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from person <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by $orderByClause$ </if> </select> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="ResultMapWithBLOBs"> select <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from person where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from person where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.demo.models.Person"> insert into person(id, name, content) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},#{content,jdbcType=LONGVARCHAR}) </insert> <insert id="insertSelective" parameterType="com.demo.models.Person"> insert into t_certstore <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null"> id, </if> <if test="name != null"> identityName, </if> <if test="content != null"> content, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null"> #{id,jdbcType=INTEGER}, </if> <if test="name!= null"> #{name,jdbcType=VARCHAR}, </if> <if test="content != null"> #{content,jdbcType=LONGVARCHAR}, </if> </trim> </insert> <update id="updateByExampleSelective" parameterType="map"> update person <set> <if test="record.id != null"> id = #{record.id,jdbcType=INTEGER}, </if> <if test="record.name!= null"> name = #{record.name,jdbcType=VARCHAR}, </if> <if test="record.content != null"> content = #{record.content,jdbcType=LONGVARCHAR}, </if> </set> <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <select id="countByExample" parameterType="com.demo.models.Person" resultType="java.lang.Integer"> select count(*) from person <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </select> ...... </mapper>
定義與Mapper.xml中sql語句對應的方法,方法名就是sql語句的id屬性,參數和返回值也要對應。
public interface PersonMapper { int countByExample(PersonExample example);int deleteByPrimaryKey(Integer id); int insert(Personrecord); int insertSelective(Person record); List<CertStore> selectByExampleWithBLOBs(PersonExample example); CertStore selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") Person record, @Param("example") PersonExample example); ...... }
使用了多個參數的時候,能夠用@Param註解給參數設置名字以區分不一樣參數,xml文件中sql語句的參數類型爲map,經過參數名訪問參數對象的屬性。如@Param(record), 可用#{record.id}訪問。還能夠指定類型,如#{record.id,jdbcType=INTEGER}。
若是隻有一個參數則不須要指定參數的名字,#{...}會直接訪問這個參數對象的屬性,若是沒有適合的屬性則直接表明當前參數。
<?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="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/testdb?autoReconnect=true" /> <property name="username" value="xxxx" /> <property name="password" value="xxxx" /> </dataSource> </environment> </environments> <settings>......</settings> <!-- 全局別名設置,在映射文件中只需寫別名,而沒必要寫出整個類路徑 --> <typeAliases>......</typeAliases> <!-- 非註解的sql映射文件配置,若是使用mybatis註解,該mapper無需配置,可是若是mybatis註解中包含@resultMap註解,則mapper必須配置,給resultMap註解使用 --> <mappers> <mapper resource="mapper/Person.xml" /> <mapper class="com.demo.mapper.CustomPersonMapper" /> ...... </mappers> </configuration>
能夠自行建立額外的sql映射xml文件或基於註解Mapper接口,可是都須要加入到Mybatis配置中的mappers元素裏。
<!-- 全局映射器啓用緩存 --> <setting name="cacheEnabled" value="true" /> <!-- 查詢時,關閉關聯對象即時加載以提升性能 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 設置關聯對象加載的形態,此處爲按需加載字段(加載字段由SQL指 定),不會加載關聯表的全部字段,以提升性能 --> <setting name="aggressiveLazyLoading" value="false" /> <!-- 對於未知的SQL查詢,容許返回不一樣的結果集以達到通用的效果 --> <setting name="multipleResultSetsEnabled" value="true" /> <!-- 容許使用列標籤代替列名 --> <setting name="useColumnLabel" value="true" /> <!-- 容許使用自定義的主鍵值(好比由程序生成的UUID 32位編碼做爲鍵值),數據表的PK生成策略將被覆蓋 --> <setting name="useGeneratedKeys" value="true" /> <!-- 給予被嵌套的resultMap以字段-屬性的映射支持 --> <setting name="autoMappingBehavior" value="FULL" /> <!-- 對於批量更新操做緩存SQL以提升性能 --> <setting name="defaultExecutorType" value="BATCH" /> <!-- 數據庫超過25000秒仍未響應則超時 --> <setting name="defaultStatementTimeout" value="25000" /> ......
typeHandlers用來自定義映射規則,如你能夠自定義將Character映射爲varchar,plugins元素則放了一些攔截器接口,你能夠繼承他們並作一些切面的事情。更多配置如如properties,objectFactory等,能夠參考ibatis-3-config.dtd文檔。
使用Spring時,不須要此配置文件,而是使用針對Spring的專門的配置文件(配置bean)。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session=sqlSessionFactory .openSession(true); /** * 映射sql的標識字符串, * com.demo.mappers.personMapper是personMapper.xml文件中mapper標籤的namespace屬性的值, * getPerson是select標籤的id屬性值,經過select標籤的id屬性值就能夠找到要執行的SQL */ String statement = "com.demo.mappers.personMapper.getPerson";//映射sql的標識字符串 //執行查詢返回一個惟一user對象的sql Person person = session.selectOne(statement, 1); System.out.println(person); PersonMapper personMapper = session.getMapper(PersonMapper.class); personMapper.insert(new Pserson(......)); ...... session.commit(); session.close();
SqlSessionManager sessionManager=SqlSessionManager.newInstance(inputStream);
Configuration configuration = sessionManager.getConfiguration();
MapperRegistry mapperRegistry = configuration.getMapperRegistry();
if(!sessionManager.isManagedSessionStarted())
sessionManager.startManagedSession(true);
SqlSession接口提供了經常使用的數據庫操做方法。全部的statement參數爲xml文件中namespace加上sql語句id,如com.demo.mappers.PersonMapper.selectByPrimaryKey。
以上這些方法只須要用到XML映射文件,不須要Mapper接口。
其餘操做
能夠同過SqlSession生成Mapper類實例,經過Mapper實例調用Mapper中定義的各類數據庫操做方法。
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class); Person p=mapper.selectByPrimaryKey(1); ......
能夠直接在生成的Mapper類中額外加入自定義的數據庫操做方法。使用註解能夠沒有XML映射文件。
@Select("select * from person where name like #{name}") public Person selectPersonByName(String name); @Select("select * from person where content is not null") public List<Person> selectPersonWithContent();
註解Mapper示例
@CacheNamespace(size = 512) public interface TestMapper { @SelectProvider(type = TestSqlProvider.class, method = "getSql") @Options(useCache = true, flushCache = false, timeout = 10000) @Results(value = { @Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR), @Result(property = "testText", column = "test_text", javaType = String.class, jdbcType = JdbcType.VARCHAR) }) public TestBean get(@Param("id") String id); @SelectProvider(type = TestSqlProvider.class, method = "getAllSql") @Options(useCache = true, flushCache = false, timeout = 10000) @Results(value = { @Result(id = true, property = "id", column = "test_id", javaType = String.class, jdbcType = JdbcType.VARCHAR), @Result(property = "testText", column = "test_text", javaType = String.class, jdbcType = JdbcType.VARCHAR) }) public List<TestBean> getAll(); @SelectProvider(type = TestSqlProvider.class, method = "getByTestTextSql") @Options(useCache = true, flushCache = false, timeout = 10000) @ResultMap(value = "getByTestText") public List<TestBean> getByTestText(@Param("testText") String testText); @InsertProvider(type = TestSqlProvider.class, method = "insertSql") @Options(flushCache = true, timeout = 20000) public void insert(@Param("testBean") TestBean testBean); @UpdateProvider(type = TestSqlProvider.class, method = "updateSql") @Options(flushCache = true, timeout = 20000) public void update(@Param("testBean") TestBean testBean); @DeleteProvider(type = TestSqlProvider.class, method = "deleteSql") @Options(flushCache = true, timeout = 20000) public void delete(@Param("id") String id); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.wotao.taotao.persist.test.mapper.TestMapper"> <resultMap id="getByTestText" type="TestBean"> <id property="id" column="test_id" javaType="string" jdbcType="VARCHAR" /> <result property="testText" column="test_text" javaType="string" jdbcType="VARCHAR" /> </resultMap> </mapper>
使用註解後,能夠再也不用XML映射文件編寫SQL,而是在java類中編寫。示例以下:
public class TestSqlProvider { private static final String TABLE_NAME = "test"; public String getSql(Map<String, Object> parameters) { String uid = (String) parameters.get("id"); BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); if (uid != null) { WHERE("test_id = #{id,javaType=string,jdbcType=VARCHAR}"); } return SQL(); } public String getAllSql() { BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); return SQL(); } public String getByTestTextSql(Map<String, Object> parameters) { String tText = (String) parameters.get("testText"); BEGIN(); SELECT("test_id, test_text"); FROM(TABLE_NAME); if (tText != null) { WHERE("test_text like #{testText,javaType=string,jdbcType=VARCHAR}"); } return SQL(); } public String insertSql() { BEGIN(); INSERT_INTO(TABLE_NAME); VALUES("test_id", "#{testBean.id,javaType=string,jdbcType=VARCHAR}"); VALUES("test_text", "#{testBean.testText,javaType=string,jdbcType=VARCHAR}"); return SQL(); } public String updateSql() { BEGIN(); UPDATE(TABLE_NAME); SET("test_text = #{testBean.testText,javaType=string,jdbcType=VARCHAR}"); WHERE("test_id = #{testBean.id,javaType=string,jdbcType=VARCHAR}"); return SQL(); } public String deleteSql() { BEGIN(); DELETE_FROM(TABLE_NAME); WHERE("test_id = #{id,javaType=string,jdbcType=VARCHAR}"); return SQL(); } }
mybatis提供SelectBuilder和SqlBuilder這2個小工具來幫助咱們生成SQL語句。SelectBuilder專門用來生成select語句,而SqlBuilder則是通常性的工具,能夠生成任何SQL語句。可經過import static org.apache.ibatis.jdbc.SqlBuilder.BEGIN的方式引入SqlBuilder提供的靜態方法。
經過Map<String, Object> parameters接收Mapper接口中定義的參數。Mapper接口方法中定義使用了命名的參數如@Param("testId"),@Param("testText"),Map中的key爲參數名,若是參數沒有命名,key爲基於0的順序下標。
@Repository("testBaseDAO") public class TestBaseDAO { ...... @Autowired public void setTestMapper(@Qualifier("testMapper") TestMapper testMapper) { this.testMapper = testMapper; } ...... }
模型|數據表
Clazz
int id | int c_id |
String name | varchar c_name |
Teacher teacher | int teacher_id |
List<Student> students |
Teacher
int id | int t_id |
String name | varchar t_name |
Student
int id | int s_id |
String name | varchar s_name |
int class_id |
使用association標籤,可用屬性:
方式一:嵌套結果
<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Clazz c, Teacher t where c.teacher_id=t.t_id and c.c_id=#{id} </select> <!-- 使用resultMap映射實體類和字段之間的一一對應關係 --> <resultMap type="com.demo.models.Clazz" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" javaType="com.demo.models.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap>
方式二:嵌套查詢
<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Clazz where c_id=#{id} </select> <!-- 使用resultMap映射實體類和字段之間的一一對應關係 --> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="refB" column="teacher_id" select="getTeacher"/> </resultMap> <select id="getTeacher" parameterType="int" resultType="com.demo.Teacher"> SELECT t_id id, t_name name FROM Teacher WHERE t_id=#{id} </select>
使用collection標籤
方式一:嵌套結果
<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from Class c, Teacher t, Student s where c.teacher_id=t.t_id and c.c_id=s.c_id and c.c_id=#{id} </select> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="com.demo.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> <!-- ofType指定students集合中的對象類型 --> <collection property="students" ofType="com.demo.Student"> <id property="id" column="s_id"/> <result property="name" column="s_name"/> </collection> </resultMap>
方式二:嵌套查詢
<select id="getClazz" parameterType="int" resultMap="ClazzResultMap"> select * from class where c_id=#{id} </select> <resultMap type="com.demo.Clazz" id="ClazzResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="com.demo.Teacher" select="getTeacher"></association> <collection property="students" ofType="com.demo.Student" column="c_id" select="getStudent"></collection> </resultMap> <select id="getTeacher" parameterType="int" resultType="com.demo.Teacher"> SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id} </select> <select id="getStudent" parameterType="int" resultType="com.demo.Student"> SELECT s_id id, s_name name FROM student WHERE class_id=#{id} </select>
定義存儲過程
-- 建立存儲過程(查詢獲得男性或女性的數量, 若是傳入的是0就女性不然是男性) DELIMITER $ CREATE PROCEDURE mybatis.ges_user_count(IN sex_id INT, OUT user_count INT) BEGIN IF sex_id=0 THEN SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='女' INTO user_count; ELSE SELECT COUNT(*) FROM mybatis.p_user WHERE p_user.sex='男' INTO user_count; END IF; END $ -- 調用存儲過程 DELIMITER ; SET @user_count = 0; CALL mybatis.ges_user_count(1, @user_count); SELECT @user_count;
sql映射配置
<!-- 查詢獲得男性或女性的數量, 若是傳入的是0就女性不然是男性 --> <select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE"> CALL mybatis.ges_user_count(?,?) </select> <parameterMap type="java.util.Map" id="getUserCountMap"> <parameter property="sexid" mode="IN" jdbcType="INTEGER"/> <parameter property="usercount" mode="OUT" jdbcType="INTEGER"/> </parameterMap>
查詢
Map<String, Integer> parameterMap = new HashMap<String, Integer>(); parameterMap.put("sexid", 1); parameterMap.put("usercount", -1); sqlSession.selectOne("getUserCount", parameterMap); Integer result = parameterMap.get("usercount");
Mybatis同時提供了一級緩存和二級緩存的支持。
<cache eviction="FIFO" <!--回收策略爲先進先出,默認使用LRU算法(最近最少使用)--> flushInterval="60000" <!--自動刷新時間60s--> size="512" <!--可緩存512個引用對象,最大爲1024--> readOnly="true"/> <!--只讀-->
http://blog.csdn.net/bluesky5219/article/details/7066174
<!--建立數據映射器,數據映射器必須爲接口--> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.xxt.ibatis.dbcp.dao.UserMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 指定sqlMapConfig總配置文件,訂製的environment在spring容器中不在生效--> <property name="configLocation" value="classpath:sqlMapConfig.xml"/> <!--指定實體類映射文件,能夠指定同時指定某一包以及子包下面的全部配置文件,mapperLocations和configLocation有一個便可,當須要爲實體類指定別名時,可指定configLocation屬性,再在mybatis總配置文件中採用mapper引入實體類映射文件 --> <property name="mapperLocations" value="classpath*:com/xxt/ibatis/dbcp/**/*.xml"/> </bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean>
-------------------
spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 配置數據源 --> <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc_url}" /> <property name="username" value="${jdbc_username}" /> <property name="password" value="${jdbc_password}" /> ...... </bean> <!-- 配置Mybatis sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 實例化sqlSessionFactory時須要使用上述配置好的數據源 --> <property name="dataSource" ref="dataSource" /> <!-- 自動掃描me/gacl/mapping/目錄下的全部SQL映射xml文件, 無需Configuration.xml裏的手工配置--> <property name="mapperLocations" value="classpath:com/demo/mappers/*.xml" /> <!-- <property name="configLocation" value="classpath:configuration.xml" /> --> </bean> <!-- 配置Mybatis Mapper映射接口掃描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 掃描com.demo.mappers包以及它的子包下的全部映射接口 --> <property name="basePackage" value="com.demo.mappers" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> <!-- 另外一種配置方式:data OR mapping interface,此處忽略--> <!--<bean id="testMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="testSqlSessionFactory" /> <property name="mapperInterface" value="com.wotao.taotao.persist.test.mapper.TestMapper" /> </bean> -->
<!-- 配置Spring的事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 註解方式配置事務 --> <!-- <tx:annotation-driven transaction-manager="transactionManager" /> --> <!-- 攔截器方式配置事務 --> <tx:advice id="transactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" /> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="find*" propagation="SUPPORTS" /> <tx:method name="get*" propagation="SUPPORTS" /> <tx:method name="select*" propagation="SUPPORTS" /> <!-- <tx:method name="*" propagation="SUPPORTS" /> --> </tx:attributes> </tx:advice> <!--把事務控制在Service層 --> <aop:config> <!-- execution( public * com.demo.service.*.*(..) ) --> <aop:pointcut id="transactionPointcut" expression="execution(* com.demo.service..*Impl.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config> </beans>
建立Service接口
public interface PersonService { List<Person> getAllPerson(); }
建立Service實現類
@Service("IdOfPersonService") //自動在DI容器中註冊成Service組件 public class PersonServiceImpl implements PersonService { @Autowired PersonMapper personMapper; //dao依賴注入 @Override public List<User> getAllPerson() { return personMapper.selectByExampleWithBLOBs(null); } }
建立控制器類(不使用Spring Servlet進行分發控制)
@WebServlet("/persons") //Servlet3.0提供的註解,將一個繼承了HttpServlet類的普通java類標註爲一個Servlet,不須要在web.xml中配置 public class PersonServlet extends HttpServlet { private PersonService personService; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取全部的用戶信息 List<Person> persons = userService.getAllPersons(); request.setAttribute("persons", persons); request.getRequestDispatcher("/index.jsp").forward(request, response); } public void init() throws ServletException { //在Servlet初始化時獲取Spring上下文對象(ApplicationContext) ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); //從ApplicationContext中獲取userService userService = (UserServiceI) ac.getBean("IdOfPersonService"); } }
Spring註解的控制器(Web.xml中配置Spring Servlet,其中Spring分發控制)
@Controller @RequestMapping("/persons") public class CaseResultAnalyzeController { @Autowried private PersonService personService; @RequestMapping public ModelAndView index() { ModelAndView mv=new ModelAndView(); mv.addObject("persons", personService.getAllPersons()); mv.setViewName("/index.jsp"); return mv; } }
單首創建db.properties文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/testdb name=xxxx password=xxxx
mybatis 配置文件中引入db.properties文件
<?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="db.properties"/> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> ...... </configuration>
mybatis配置文件的configuration節點下加入typeAliases元素
<typeAliases> <!-- 爲單個類設置別名 --> <typeAlias type="com.demo.Person" alias="_Person"/> <!-- 爲整個包下的類設置別名,默認的別名就是不帶包名的類名 --> <package name="com.demo"/> </typeAliases>
而後在sql映射的XML中就可使用別名代替model類名了
<insert id="addUser" parameterType="_Person"> insert into person(id,name) values(#{id},#{name}) </insert>
方式一:
在Mapper的XML文件中使用resultMap元素定義映射關係。sql語句定義中引用映射關係。
<resultMap type="com.demo.Person" id="personResultMap"> <!-- 主鍵字段映射 --> <id property="id" column="person_id"/> <!-- 非主鍵字段映射 --> <result property="name" column="person_no"/> </resultMap> <select id="selectPersonResult" parameterType="int" resultMap="personResultMap"> select * from person where person_id=#{id} </select>
方式二:
使用sql語句生成和模型對象屬性名相同的字段別名
<select id="selectOrder" parameterType="int" resultType="com.demo.Person"> select person_id id, person_name name from person where person_id=#{id} </select>
<isNotEmpty prepend="and" property="name"> NAME like '%'||#name#||'%' </isNotEmpty>
這種方式沒法走索引(走索引只限於like 'xxx%'的形式,%xxx和%xxx%都不行),也有說有時候會遇到檢索不到數據的(參考)
http://www.cnblogs.com/xdp-gacl/tag/MyBatis%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93/
http://www.cnblogs.com/ibook360/archive/2012/07/16/2594056.html
http://www.cnblogs.com/fsjohnhuang/category/618850.html (MyBatis魔法堂)
------------------------
MyBatis 全局配置文件的各主要元素基本和 iBatis 相同,只是在用法和個別名稱上作了調整。
MyBatis 的 DTD 文件已經包含在發佈包下的 mybatis-3.0.x.jar 包中。iBatis 配置文件的根元素是 <sqlMapConfig>,MyBatis 使用的是 <configuration>。
<?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> ...... </configuration>
MyBatis 可以根據配置信息和數據庫創建鏈接,並應用給定的鏈接池信息和事務屬性。MyBatis 封裝了這些操做,最終暴露一個 SqlSessionFactory 實例供開發者使用,從名字能夠看出來,這是一個建立 SqlSession 的工廠類,經過 SqlSession 實例,開發者可以直接進行業務邏輯的操做,而不須要重複編寫 JDBC 相關的樣板代碼。根據全局配置文件生成 SqlSession 的代碼以下:
Reader reader = Resources.getResourceAsReader("Configuration.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = sqlSessionFactory.openSession();
Resources 是 MyBatis 提供的一個工具類,它用於簡化資源文件的加載,它能夠訪問各類路徑的文件。Mybatis如今已經沒有SqlMapClient了,使用的則是SqlSession.在原來的基礎上加了像selectMap,selectList,selectOne這樣的方法,使用更方便了。
ibatis配置事務管理器和數據源的方式以下:
<transactionManager type="JDBC" > <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="${driver}"/> <!-- 其餘數據源信息省略 --> </dataSource> </transactionManager>
在MyBatis中配置事務管理器和數據源的方式:
<environments default="demo"> <environment id="demo"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="JDBC.Driver" value="${driver}"/> <!-- 其餘數據源信息省略 --> </dataSource> </environment> </environments>
在 iBatis 中指定映射文件的方式以下:
<sqlMap resource=... /> <sqlMap resource=... /> <sqlMap resource=... />
在 MyBatis 中指定映射文件的方式:
<mappers> <mapper resource=... /> <mapper resource=... /> </mappers>
DataSource ds = …… // 獲取一個 DataSource TransactionFactory txFactory = new JdbcTransactionFactory(); Environment env = new Environment("demo", txFactory, ds); Configuration cfg = new Configuration(env); cfg.addMapper(UserInfoMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfg);
結合前面的配置文件,很容易理解這段代碼的意思,不過,須要注意的是 Configuration 的 addMapper() 方法,該方法的參數一般是一個接口,能夠在接口裏面定義若干方法,在方法上使用註解來指定映射的 SQL 語句。
// 映射 SQL 綁定接口 public interface UserInfoMapper { @Select("select * from userinfo where userid = #{userid}") public UserInfo getUserInfo(int userid); } // 接口綁定對應的數據訪問方法 try { //UserInfo userinfo = (UserInfo) sqlSession.selectOne ("mybatis.demo.UserInfoMapper.selectUser", 2); UserInfoMapper userinfoMapper = sqlSession.getMapper(UserInfoMapper.class); UserInfo userinfo = userinfoMapper.getUserInfo(1); System.out.println(userinfo); } finally { sqlSession.close(); }
<?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="mybatis.demo.UserInfoMapper"> <select id="selectUser" parameterType="int" resultType="mybatis.demo.UserInfo"> select * from UserInfo where userid =#{userid} </select> </mapper>
在 iBatis 中,namespace 不是必需的,且它的存在沒有實際的意義。在 MyBatis 中,namespace 終於派上用場了,它使得映射文件與接口綁定變得很是天然。Ibatis用的parameterClass在mybatis中已經永不了了,mybatis裏應該使用parameterType。另外resultMap裏面也不能繼續使用了改爲了type。
同時數據類型的聲明和ibatis有了很大的差異,ibatis能夠像下面這樣寫
insert into M_HEALTHSPECIALYTYPE(FCODE,FCHARGE,FTYPECONTENT,FID,FMARK) values (#FCODE:VARCHAR2#,#FCHARGE:VARCHAR2#,#FTYPECONTENT:VARCHAR2#,#FID#,#FMARK:VARCHAR2#)
而在mybatis的話通常是這樣弄的:
insert into M_HEALTHSPECIALYTYPE(FCODE,FCHARGE,FTYPECONTENT,FID,FMARK) values (#{FCODE,jdbcType=VARCHAR},#{FCHARGE,jdbcType=VARCHAR},#{FTYPECONTENT,jdbcType=VARCHAR},#{FID},#{FMARK,jdbcType=VARCHAR})
針對映射文件,首先是一系列的屬性名稱的改變,這些僅僅是名稱的改變,用法和含義並無發生變化:
· 和全局配置文件同樣,因爲 DTD 約束髮生變化,根元素也由原來的 <sqlMap> 調整爲 <mapper>。
· <select> 等元素的 parameterClass 屬性改成了 parameterType 屬性。
· <select> 等元素的 resultClasss 屬性改成了 resultType 屬性。
· <parameterMap> 等元素的 class 屬性改成了 type 屬性。
· <result> 元素的 columnIndex 屬性被移除了。
· 嵌套參數由 #value# 改成了 #{value}。
· <parameter> 等元素的 jdbcType 屬性取值中,原來的 "ORACLECURSOR" 取值改成了如今的 "CURSOR","NUMBER" 取值改成了 "NUMERIC"。
try { UserInfo userinfo = (UserInfo) sqlSession.selectOne ("mybatis.demo.UserInfoMapper.getUser", 2); System.out.println(userinfo); } finally { sqlSession.close(); }
須要注意的是,SqlSession 的使用必需遵照上面的格式,即在 finally 塊中將其關閉。以保證資源獲得釋放,防止出現內存泄露!以上就是一個簡單而完整的 MyBatis 程序。其中涉及了全局配置文件,映射文件,構建 SqlSession 對象,執行數據訪問操做等四個步驟。
iBatis 中調用存儲過程的方式(經過使用 <procedure> 元素進行存儲過程的定義):
<procedure id="getValues" parameterMap="getValuesPM"> { ? = call pkgExample.getValues(p_id => ?) } </procedure>
在 MyBatis 中,<proccedure> 元素已經被移除,經過 <select>、<insert> 和 <update> 進行定義:
<select id="getValues" parameterMap="getValuesPM" statementType="CALLABLE"> { ? = call pkgExample.getValues(p_id => ?)} </select>
如上所示,經過 statementType 屬性將該語句標識爲存儲過程而非普通 SQL 語句。
總結:
經過前面的示例能夠看出,MyBatis 在編碼中的最大的改變就是將一個最經常使用的 API 由SqlMapClient 改成SqlSessionFactory。另外,類型處理器接口也由原來的 TypeHandlerCallback 改成了 TypeHandler。最後 DataSourceFactory 也進行了調整,移動到 org.apache.ibatis.datasource 包下,其中的方法也做了微調。總之,代碼層面公開的部分改動較少,不會給開發者形成較大的移植成本。