MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
以前都是用Hibernate比较多,项目中使用到的Mybatis封装的Dao也是别人封装好的。今天第一次看Mybatis文档,写一个简单的demo加深印象。
Mybatis入门
开发环境配置
新建一个maven项目:
加入mysql-connector-java
和mybatis
,还有Lombok
(Lombok不是必须的)的依赖: 4.0.0 com.fengyuan mybatis-demo 0.0.1-SNAPSHOT org.projectlombok lombok 1.14.4 mysql mysql-connector-java 5.1.38 org.mybatis mybatis 3.2.8 org.apache.maven.plugins maven-compiler-plugin
建表
在mysql中新建数据库mybatisdemo
,并创建student
表:
表中有两条记录:
创建实体类
创建表对应的Model,Student
类:
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
,在其中配置数据源。
其中,<typeAliases>标签内指定的是你定义的实体类的别名,方便之后使用。
定义映射文件
在mybatis文件夹底下新建一个mapper文件夹,存放映射文件,在其中新建student表对应的映射文件studentMapper.xml
namespace是唯一的,namespace有点像包名+类名,id像是方法名。parameterType是方法的参数类型,resultType中的"Student"就是前面定义的别名,是方法的返回类型。
定义完映射文件,将其注册到配置文件中:测试
完成以上步骤,就可以开始测试了。
测试类: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必须与对应接口的某个对应的方法名一致,如下:
注册接口
测试
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语句,比第一种方式要直观、而且“面向对象”了很多。 此时的项目结构:
CURD
除了前面演示的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 ListlistAllStudents();}
使用XML文件映射
如果是用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 ListlistAllStudents();}
然后,在XML文件中,定义好对应的sql:
insert into student(name, age) values(#{name}, #{age}) delete from student where name = #{name} update student set age = #{age} where id = #{id}
注意namespace与id要与接口中一一对应。
注册到配置文件中
或者
测试
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); Liststudents = studentDao.listAllStudents(); System.out.println(students); // 提交事务 sqlSession.commit(); } finally { sqlSession.close(); } } public static void main(String[] args) { }}
Mybatis-Generator
手动书写Mapping映射文件不仅繁琐而且容易出错,通过Mybatis-Generator,可以帮我们自动生成相关的文件。以下内容是从中学习的,感谢博主。
准备
建表
这边我们还是用前面的student
表来作为示例。
我这边用的是mybatis-generator-core
包mybatis-generator-core-1.3.2.jar
。数据库驱动
同样,数据库用的是mysql,所以用了mysql-connector-java-5.1.25.jar
。配置文件
generatorConfig.xml
:
相关文件截图:
执行
在命令行执行命令:
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
:id, name, age delete from studentwhere id = #{id,jdbcType=INTEGER} insert into student (id, name, age )values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER} ) insert into student id, name, age, #{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, update student name = #{name,jdbcType=VARCHAR}, age = #{age,jdbcType=INTEGER}, update studentset name = #{name,jdbcType=VARCHAR}, age = #{age,jdbcType=INTEGER}where id = #{id,jdbcType=INTEGER} -
在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);}