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不是必须的)的依赖:
<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
表:
表中有两条记录:
创建实体类
创建表对应的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
,在其中配置数据源。
<?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文件夹底下新建一个mapper文件夹,存放映射文件,在其中新建student表对应的映射文件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.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语句,比第一种方式要直观、而且“面向对象”了很多。
此时的项目结构:
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 List<Student> listAllStudents();
}
使用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 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) {
}
}
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
:
<?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); }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。