MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎全部的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis 使用簡單的 XML或註解用於配置和原始映射,將接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。html
之前都是用Hibernate比較多,項目中使用到的Mybatis封裝的Dao也是別人封裝好的。今天第一次看Mybatis文檔,寫一個簡單的demo加深印象。java
新建一個maven項目:
加入mysql-connector-java
和mybatis
,還有Lombok
(Lombok不是必須的)的依賴:mysql
<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.fengyuan</groupId> <artifactId>mybatis-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.14.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
在mysql中新建數據庫mybatisdemo
,並建立student
表:
sql
表中有兩條記錄:
數據庫
建立表對應的Model,Student
類:apache
package com.fengyuan.domain; import lombok.Data; public @Data class Student { private int id; private String name; private int age; }
在項目中新建mybatis文件夾,在其中添加Mybatis的配置文件mybatis-conf.xml
,在其中配置數據源。session
<?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> <typeAliases> <typeAlias alias="Student" type="com.fengyuan.domain.Student" /> </typeAliases> <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/mybatisdemo" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> </configuration>
其中,<typeAliases>標籤內指定的是你定義的實體類的別名,方便以後使用。mybatis
在mybatis文件夾底下新建一個mapper文件夾,存放映射文件,在其中新建student表對應的映射文件studentMapper.xml
app
<?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.fengyuan.domain.StudentMapper"> <select id="getStudentById" parameterType="int" resultType="Student"> select * from student where id=#{id} </select> </mapper>
namespace是惟一的,namespace有點像包名+類名,id像是方法名。parameterType是方法的參數類型,resultType中的"Student"就是前面定義的別名,是方法的返回類型。
定義完映射文件,將其註冊到配置文件中:框架
<?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> <typeAliases> <typeAlias alias="Student" type="com.fengyuan.domain.Student" /> </typeAliases> <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/mybatisdemo" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!--註冊映射文件--> <mappers> <mapper resource="mybatis/mapper/studentMapper.xml" /> </mappers> </configuration>
完成以上步驟,就能夠開始測試了。
測試類:
package com.fengyuan.client; import java.io.IOException; import java.io.Reader; 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 com.fengyuan.domain.Student; public class Main { public static void main(String[] args) { Reader reader = null; try { // 加載配置文件 reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml"); } catch (IOException e) { e.printStackTrace(); } // 構建SqlSession工廠,並從工廠裏打開一個SqlSession SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 找到對應的sql String statement = "com.fengyuan.domain.StudentMapper.getStudentById"; // 傳入參數id=1,執行sql,返回查詢結果 Student student = sqlSession.selectOne(statement, 1); System.out.println(student); } finally { sqlSession.close(); } } }
執行結果:
Student(id=1, name=Can Liu, age=40)
表中id爲1的記錄已經取出來了。
項目結構:
前面的這種映射方式,雖然能夠用,可是要用字符串來找對應的sql很不方便,還有可能出錯。mybatis提供了註解的方式,更簡單也更直觀。
在項目中建立一個Dao接口StudentDao.java
package com.fengyuan.dao; import org.apache.ibatis.annotations.Select; import com.fengyuan.domain.Student; public interface StudentDao { @Select("select * from student where id = #{id}") public Student getStudentById(int id); }
把剛纔寫在映射文件中的sql語句寫在@Select註解中便可,這樣一來映射文件studentMappper.xml
就不用了。
固然,若是要用xml來映射也是能夠的,接口中只寫方法,不要加註解。此時要求namespace必須與對應的接口全類名一致,id必須與對應接口的某個對應的方法名一致,以下:
<?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.fengyuan.dao.StudentDao"> <select id="getStudentById" parameterType="int" resultType="Student"> select * from student where id=#{id} </select> </mapper>
<?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> <!-- 別名 --> <typeAliases> <typeAlias alias="Student" type="com.fengyuan.domain.Student" /> </typeAliases> <!-- 數據源 --> <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/mybatisdemo" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 註冊映射文件 --> <!-- <mappers> <mapper resource="mybatis/mapper/studentMapper.xml" /> </mappers> --> <!-- 註冊接口 --> <mappers> <mapper class="com.fengyuan.dao.StudentDao" /> </mappers> </configuration>
package com.fengyuan.client; import java.io.IOException; import java.io.Reader; 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 com.fengyuan.dao.StudentDao; import com.fengyuan.domain.Student; public class Main { public static void main(String[] args) { Reader reader = null; try { // 加載配置文件 reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml"); } catch (IOException e) { e.printStackTrace(); } // 構建SqlSession工廠,並從工廠裏打開一個SqlSession SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = sqlSessionFactory.openSession(); // 若是配置文件中沒有註冊接口,能夠在代碼裏註冊 //sqlSession.getConfiguration().addMapper(StudentDao.class); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); // 直接調用接口的方法,傳入參數id=1,返回Student對象 Student student = studentDao.getStudentById(1); System.out.println(student); } finally { sqlSession.close(); } } }
如代碼中的註釋,除了在配置文件中註冊接口,也能夠在代碼中用sqlSession.getConfiguration().addMapper(StudentDao.class);
來註冊。
而後就能夠直接調用接口的方法來執行對應的sql語句,比第一種方式要直觀、並且「面向對象」了不少。
此時的項目結構:
除了前面演示的select語句,這邊補充一下其餘的示例。
在接口studentDao.java
中定義相應的方法,並在註解中寫上對應的sql:
package com.fengyuan.dao; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import com.fengyuan.domain.Student; public interface StudentDao { @Select("select * from student where id= #{id}") public Student getStudentById(int id); @Insert("insert into student(name, age) values(#{name}, #{age})") public int addStudent(Student student); @Delete("delete from student where name = #{name}") public int removeStudentByName(String name); @Update("update student set age = #{age} where id = #{id}") public int updateStudent(Student student); @Select("select * from student") public List<Student> listAllStudents(); }
若是是用XML文件,接口中只要定義好方法:
package com.fengyuan.dao; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import com.fengyuan.domain.Student; public interface StudentDao { public Student getStudentById(int id); public int addStudent(Student student); public int removeStudentByName(String name); public int updateStudent(Student student); public List<Student> listAllStudents(); }
而後,在XML文件中,定義好對應的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.fengyuan.dao.StudentDao"> <select id="getStudentById" parameterType="int" resultType="Student"> select * from student where id=#{id} </select> <insert id="addStudent" parameterType="Student"> insert into student(name, age) values(#{name}, #{age}) </insert> <delete id="removeStudentByName" parameterType="String"> delete from student where name = #{name} </delete> <update id="updateStudent" parameterType="Student"> update student set age = #{age} where id = #{id} </update> <select id="listAllStudents" resultType="Student"> select * from student </select> </mapper>
注意namespace與id要與接口中一一對應。
<mappers> <mapper class="com.fengyuan.dao.StudentDao" /> </mappers>
或者
<mappers> <mapper resource="mybatis/mapper/studentMapper.xml" /> </mappers>
package com.fengyuan.client; import java.io.Reader; 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 com.fengyuan.dao.StudentDao; import com.fengyuan.domain.Student; public class Main { private static Reader reader; private static SqlSessionFactory sqlSessionFactory; static { try { reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取sqlSession * @return */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } /** * 查詢 */ public static void testQuery() { SqlSession sqlSession = getSqlSession(); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); // 根據id返回Student對象 Student student = studentDao.getStudentById(1); System.out.println(student); } finally { sqlSession.close(); } } /** * 新增 */ public static void testInsert() { SqlSession sqlSession = getSqlSession(); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); // 新建一個student對象 Student student = new Student(); student.setName("Aaron"); student.setAge(24); // 插入到表中 studentDao.addStudent(student); // 提交事務 sqlSession.commit(); } finally { sqlSession.close(); } } /** * 更新 */ public static void testUpdate() { SqlSession sqlSession = getSqlSession(); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); // 取出student記錄,修改年齡,再更新到數據庫 Student student = studentDao.getStudentById(2); student.setAge(44); studentDao.updateStudent(student); // 提交事務 sqlSession.commit(); } finally { sqlSession.close(); } } /** * 刪除 */ public static void testRemove() { SqlSession sqlSession = getSqlSession(); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); studentDao.removeStudentByName("cly"); // 提交事務 sqlSession.commit(); } finally { sqlSession.close(); } } /** * 以List返回student表中全部記錄 */ public static void testGetAll() { SqlSession sqlSession = getSqlSession(); try { // 獲取映射類 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); List<Student> students = studentDao.listAllStudents(); System.out.println(students); // 提交事務 sqlSession.commit(); } finally { sqlSession.close(); } } public static void main(String[] args) { } }
手動書寫Mapping映射文件不只繁瑣並且容易出錯,經過Mybatis-Generator,能夠幫咱們自動生成相關的文件。如下內容是從這篇博客中學習的,感謝博主。
建表
這邊咱們仍是用前面的student
表來做爲示例。
mybatis-generator-core
包
我這邊用的是mybatis-generator-core-1.3.2.jar
。
數據庫驅動
一樣,數據庫用的是mysql,因此用了mysql-connector-java-5.1.25.jar
。
配置文件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 location="mysql-connector-java-5.1.25.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <property name="suppressDate" value="true"/> <property name="suppressAllComments" value="true"/> </commentGenerator> <!--數據庫連接地址帳號密碼--> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatisdemo" userId="root" password="123456"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!--生成Model類存放位置--> <javaModelGenerator targetPackage="com.fengyuan.model" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!--生成映射文件存放位置--> <sqlMapGenerator targetPackage="com.fengyuan.mapping" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!--生成Dao類存放位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="com.fengyuan.dao" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!--生成對應表及類名--> <table tableName="student" domainObjectName="Student" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>
相關文件截圖:
在命令行執行命令:
java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite
輸出Mybatis Generator finished successfully.,表示執行成功,在指定的路徑生成了相應文件。若是有問題會輸出相應的提示。
根據配置,咱們生成了三個文件。
在src/main/java中com.fengyuan.model中生成了Student.java
:
package com.fengyuan.model; public class Student { private Integer id; private String name; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
在src/main/java中com.fengyuan.mapping中生成了StudentMapper.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.fengyuan.dao.StudentMapper" > <resultMap id="BaseResultMap" type="com.fengyuan.model.Student" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="INTEGER" /> </resultMap> <sql id="Base_Column_List" > id, name, age </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > select <include refid="Base_Column_List" /> from student where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" > delete from student where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.fengyuan.model.Student" > insert into student (id, name, age ) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER} ) </insert> <insert id="insertSelective" parameterType="com.fengyuan.model.Student" > insert into student <trim prefix="(" suffix=")" suffixOverrides="," > <if test="id != null" > id, </if> <if test="name != null" > name, </if> <if test="age != null" > age, </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="age != null" > #{age,jdbcType=INTEGER}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.fengyuan.model.Student" > update student <set > <if test="name != null" > name = #{name,jdbcType=VARCHAR}, </if> <if test="age != null" > age = #{age,jdbcType=INTEGER}, </if> </set> where id = #{id,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="com.fengyuan.model.Student" > update student set name = #{name,jdbcType=VARCHAR}, age = #{age,jdbcType=INTEGER} where id = #{id,jdbcType=INTEGER} </update> </mapper>
在src/main/java中com.fengyuan.dao中生成了StudentMapper.java
:
package com.fengyuan.dao; import com.fengyuan.model.Student; public interface StudentMapper { int deleteByPrimaryKey(Integer id); int insert(Student record); int insertSelective(Student record); Student selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(Student record); int updateByPrimaryKey(Student record); }