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); }