- mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
- mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。
- 最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
MyBatis官网地址
MyBatis开发步骤:
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.6version>
dependency>

package com.zhxd.domain;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", usernanme='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="UserMapper">
<select id="findAll" resultType="com.zhxd.domain.User">
select * from user
select>
mapper>
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">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test">property>
<property name="username" value="root">property>
<property name="password" value="root">property>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/zhxd/mapper/UserMapper.xml">mapper>
mappers>
configuration>
package com.zhxd.test;
import com.zhxd.domain.User;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMyBatis {
//查询所有数据
@Test
public void test1() throws IOException {
//加载MyBatis核心配置类文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获得sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句
List<User> userList = sqlSession.selectList("UserMapper.findAll");
//打印结果
System.out.println(userList);
//释放资源
sqlSession.close();
}
}
:根标签
namespace: 命名空间,与语句id一起组成查询的标识 ,分别代表查询、插入、删除、更新操作

<insert id="addUser" parameterType="com.zhxd.domain.User">
insert into user values(#{id}, #{username}, #{password});
insert>
//数据库插入操作
@Test
public void test2() throws IOException {
User user = new User();
user.setUsername("zhxd");
user.setPassword("12345678");
//加载MyBatis核心配置类文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获得sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句
sqlSession.insert("UserMapper.addUser", user);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
insert标签parameterType属性指定要插入的数据类型#{实体属性名}方式引用实体中的属性值sqlSession.insert(“命名空间.id”,实体对象)sqlSession.commit()
<update id="updateUser" parameterType="com.zhxd.domain.User">
update user set username = #{username},password=#{password} where id = #{id}
update>
//数据库更新操作
@Test
public void test3() throws IOException {
User user = new User();
user.setId(1);
user.setUsername("marry");
user.setPassword("10000");
//加载MyBatis核心配置类文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获得sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句
sqlSession.update("UserMapper.updateUser", user);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
update标签sqlSession.update(“命名空间.id”,实体对象)
<delete id="delUser" parameterType="java.lang.Integer">
delete from user where id = #{id}
delete>
//删除数据操作
@Test
public void test4() throws IOException {
int id = 1;
//加载MyBatis核心配置类文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获得sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句
sqlSession.delete("UserMapper.delUser", id);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
delete标签#{任意字符串}方式引用传递的单个参数sqlSession.delete(“命名空间.id”,Object)< environments>:数据库环境的配置,支持多环境配置,子标签如下:
:id指定当前环境名称,environment拥有、子标签
:指定事务管理类型 :指定当前数据源类型其中,事务管理器(transactionManager)类型有两种:
数据源(dataSource)类型有三种:
:主要介绍它的子标签:实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://127.0.0.1:3306/test
jdbc.username = root
jdbc.password = root
在配置文件中进行加载:
<properties resource="jdbc.properties">properties>
:类型别名是为Java 类型设置一个短的名字。原来的类型名称配置如下

上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名:
SqlSession工厂构建器SqlSessionFactoryBuilder,常用API:SqlSessionFactory build(InputStream inputStream),通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象 //加载MyBatis核心配置类文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获得sqlSession工厂对象
SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = factoryBuilder.build(resourceAsStream);
//获得sqlSession对象
其中, Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。
| 方法 | 解释 |
|---|---|
| openSession() | 会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交该事务,更新操作数据才会持久化到数据库中 |
| openSession(boolean autoCommit) | 参数为是否自动提交,如果设置为true,那么不需要手动提交事务 |
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//获得sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
T selectOne(String statement, Object parameter) :查询返回一个对象 List selectList(String statement, Object parameter) :查询返回一个列表int insert(String statement, Object parameter):插入数据 int update(String statement, Object parameter):更新数据int delete(String statement, Object parameter):删除数据void commit():提交事务 void rollback():回滚事务采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper 接口开发需要遵循以下规范:

package com.zhxd.dao;
import com.zhxd.domain.User;
public interface UserMapper {
User findById(int id);
}
编写映射文件:
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhxd.dao.UserMapper">
<select id="findById" parameterType="int" resultType="user">
select * from user where id = #{id}
select>
mapper>
测试:
@Test
public void test() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//使用MyBatis生成的UserMapper接口的实现类
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findById(2);
System.out.println(user);
}
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件,这种情况在我们的多条件组合查询中经常会碰到。
sql语句 <select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id != 0">
and id = #{id}
if>
<if test="username != null">
and username = #{username}
if>
<if test="password != null">
and password = password
if>
where>
select>
@Test
public void test2() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("liming");
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.findByCondition(user);
System.out.println(userList);
}

循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
<select id="findByIds" resultType="user" parameterType="list">
select * from user
<where>
<foreach collection= "list" open = "id in(" close=")" item="id" separator=",">
#{id}
foreach>
where>
select>
@Test
public void test3() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Integer> idList = new ArrayList<Integer>();
idList.add(1); idList.add(2); idList.add(3);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.findByIds(idList);
System.out.println(userList);
}

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分)。

typeHandlers标签可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。例如需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。


为User添加birthday属性,类型为Date类型,为数据库添加birthday字段类型为bigint类型
开发步骤:
BaseTypeHandlersetNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时 mysql的字符串类型转换成 java的Type类型的方法。package com.zhxd.utils.typehandler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class MyDateTypeHandler extends BaseTypeHandler<Date>{
//将Java数据类型转化成数据库的数据类型
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
Long time = date.getTime();
preparedStatement.setString(i, time+ "");
}
//将数据库的数据库类型转换成java的数据类型
//String s参数 需要转换的字段名称
//resultSet 查询出来的结果集
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
Long time = resultSet.getLong(s);
Date date = new Date(time);
return date;
}
//将数据库的数据库类型转换成java的数据类型
//int i参数代表的是第几个字段的意思
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
Long time = resultSet.getLong(i);
Date date = new Date(time);
return date;
}
//将数据库的数据库类型转换成java的数据类型
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
Long time = callableStatement.getLong(i);
Date date = new Date(time);
return date;
}
}
<typeHandlers>
<typeHandler handler="com.zhxd.utils.typehandler.MyDateTypeHandler">typeHandler>
typeHandlers>
@Test
public void test4() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("jacky");
user.setPassword("88888888");
user.setBirthday(new Date(2000, 1, 19));
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.addUser(user);
sqlSession.commit();
}

MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即
可获得分页的相关数据。
首先在UserMapper接口中添加查询用户的方法:

编写好Sql语句:

分页的开发步骤:
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>3.7.5version>
dependency>
<dependency>
<groupId>com.github.jsqlparsergroupId>
<artifactId>jsqlparserartifactId>
<version>0.9.1version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql">property>
plugin>
plugins>
plugins>中嵌套,在plugin的拦截器(interceptor)属性配置上分页插件,在分页插件中配置方言,指定数据库。@Test
public void test5() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(1,3);
List<User> userPage = mapper.findAllUser();
for (User user:userPage) {
System.out.println(user);
}
sqlSession.close();
}

PageHelp对象设置分页:
PageHelper.startPage(pageNum,pageSIze):pageNum:页数,pageSize:显示的条数获得分页相关的其他参数,需要用到PageInfo对象
PageInfo(List list) int getTotal():总条数int getPages():总页数int getPageNum():当前页int getPageSize():每页显示长度boolean isIsFirstPage():是否是第一页boolean isIsLastPage():是否是最后一页@Test
public void test5() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(1,3);
List<User> userPage = mapper.findAllUser();
for (User user:userPage) {
System.out.println(user);
}
//获取分页的参数
PageInfo<User> userPageInfo = new PageInfo<User>(userPage);
//总条数
System.out.println("总条数:"+ userPageInfo.getTotal());
//总页数
System.out.println("总页数:"+userPageInfo.getPages());
//当前页
System.out.println("当前页:"+userPageInfo.getPageNum());
//每页显示的长度
System.out.println("每页显示长度:"+userPageInfo.getPageSize());
//是否是第一页
System.out.println("是否是第一页:"+userPageInfo.isIsFirstPage());
//是否是最后一页
System.out.println("是否是最后一页:"+userPageInfo.isIsLastPage());
sqlSession.close();
}

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户。

搭建对应的环境:


package com.zhxd.domain;
import java.util.Date;
public class Order {
private int id;
private Date orderTime;
private double total;
private User user;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getOrderTime() {
return orderTime;
}
public void setOrderTime(Date orderTime) {
this.orderTime = orderTime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Order{" +
"id=" + id +
", orderTime=" + orderTime +
", total=" + total +
", user=" + user +
'}';
}
}
一对一查询的语句:
select *,o.id oid from orders o join user u on u.id = o.uid;

问题的关键在于查询出来的数据如何解决数据表字段与实体没有一一对应的映射关系
标签进行映射处理:
:对应实体中的id:使用两个属性进行关系映射column:数据表字段名字property: 实体属性名字
<resultMap id="orderMap" type="com.zhxd.domain.Order">
<id column="oid" property="id">id>
<result column="ordertime" property="orderTime">result>
<result column="total" property="total">result>
<result column="uid" property="user.id">result>
<result column="username" property="user.username">result>
<result column="password" property="user.password">result>
<result column="birthday" property="user.birthday">result>
resultMap>
把查询结果(resultType)的类型改为resultMap的id值
<select id="findOrders" resultMap="orderMap">
select *,o.id oid from orders o join user u on u.id = o.uid
select>
还可以对上述代码做一个优化,使用association进行页映射处理,可以指定当前实体的属性名对应的属性类型
property:当前实体(order)的属性名称javaType:当前实体(order)中的属性类型(com.zhxd.domain.User)
<resultMap id="orderMap" type="com.zhxd.domain.Order">
<id column="oid" property="id">id>
<result column="ordertime" property="orderTime">result>
<result column="total" property="total">result>
<association property="user" javaType="user">
<id column="uid" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
association>
resultMap>
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单。
为User新增一个orderList属性,代表该用户下的所有订单:
package com.zhxd.domain;
import java.util.Date;
import java.util.List;
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//新增属性
private List<Order> orderList;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
//重写toString
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
", orderList=" + orderList +
'}';
}
}
查询用户下的订单SQL语句:
select *, o.id oid from user u left outer join orders o on u.id = o.uid;

修改映射文件UserMapper.xml中的findAllUser:
<resultMap id="userMap" type="user">
<id column="id" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
<collection property="orderList" ofType="order">
<id column="oid" property="id">id>
<result column="ordertime" property="orderTime">result>
<result column="total" property="total">result>
collection>
resultMap>
<select id="findAllUser" resultMap="userMap">
select *, o.id oid from user u left outer join orders o on u.id = o.uid
select>
使用标签封把结果封装成集合:
-
- property:集合名称
- ofType:当前集合的类型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用,多对多查询的需求:查询用户同时查询出该用户的所有角色,多对多查询的做法和一对多相似,只不过多了张中间表

新建角色实体类:
package com.zhxd.domain;
public class Role {
private int id;
private String roleName;
private String roleDecs;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDecs() {
return roleDecs;
}
public void setRoleDecs(String roleDecs) {
this.roleDecs = roleDecs;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", roleDecs='" + roleDecs + '\'' +
'}';
}
}
为User添加属性
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//新增roleList属性
private List<Role> roleList;
//省略get、set和toString方法
}
新建sys_role和sys_user_role表


查询用户被哪些角色所拥有,用户拥有哪些角色的SQL语句:
select * from user u join sys_user_role ur on u.id = ur.userId join sys_role r on r.id=ur.roleId;

修改UserMapper.xml
<resultMap id="userMap" type="user">
<id column="id" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
<collection property="roleList" ofType="role">
<id column="roleid" property="id">id>
<result column="roleName" property="roleName">result>
<result column="roleDesc" property="roleDesc">result>
collection>
resultMap>
<select id="findAllUser" resultMap="userMap">
select * from sys_user u join sys_user_role ur on u.id = ur.userId join sys_role r on r.id=ur.roleId
select>
测试:
@Test
public void test5() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.findAllUser();
for(User user:userList) {
System.out.println(user);
}
sqlSession.close();
}

@Insert:实现新增@Update:实现更新@Delete:实现删除Select:实现查询Result:实现结果集封装Results:可以与@Result 一起使用,封装多个结果集One::实现一对一结果集封装@Many:实现一对多结果集封装新建一个UserMapper接口,在UserMapper中添加增删改查方法:
public interface UserMapper{
//查询所有用户
public List<User> findAllUser();
//根据id查询用户
public User findUserById(long id);
//插入用户
public void addUser(User user);
//更新用户信息
public void updateUser(User user);
//删除用户
public void delUser(long id);
}
在方法上面添加@Select(“SQL语句”)/ @Insert(“SQL语句”)/ @Delete(“SQL语句”)/ @Update(“SQL语句”)
public interface UserMapper{
@Select("select * from user")
//查询所有用户
public List<User> findAllUser();
@Select("select * from user where id = #{id}")
//根据id查询用户
public User findUserById(long id);
@Insert("insert into user values(#{id},#{username},#{password},#{birthday})")
//插入用户
public void addUser(User user);
@Update("update user set username = #{username},password = #{password},birthday= #{birthday} where id = #{id}")
//更新用户信息
public void updateUser(User user);
@Delete("delete from user where id = #{id}")
//删除用户
public void delUser(long id);
}
在MyBatis配置文件中配置需要扫描的包:
<mappers>
<package name="com.zhxd.dao">package>
mappers>
测试代码:
public class TestAnno {
private UserMapper mapper;
@Before//在执行测试代码前先执行Before中的内容
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(resourceAsStream).openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
}
@Test
//查询所有用户
public void testSelectAll() {
List<User> userList = mapper.findAllUser();
for (User user : userList) {
System.out.println(user);
}
}
@Test
//根据id查询用户
public void testSelectById() {
User user = mapper.findUserById(2);
System.out.println(user);
}
@Test
//插入用户
public void insertUser() {
User user = new User();
user.setUsername("lingling");
user.setPassword("12345678910");
user.setBirthday(new Date(2008, 10, 29));
mapper.updateUser(user);
}
@Test
//更新用户信息
public void updateUser() {
User user = new User();
user.setId(12);
user.setUsername("lisa");
user.setPassword("12345678910");
user.setBirthday(new Date(2008, 10, 29));
mapper.updateUser(user);
}
@Test
//删除用户
public void delUser() {
mapper.delUser(12);
}
}
实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
@Results:代替的是标签该注解中可以使用单个@Result注解,也可以使用@Result集标签和标签column:数据库的列名property:需要装配的属性名one:需要使用的@One 注解(@Result(one=@One)()))many:需要使用的@Many 注解(@Result(many=@many)()))@One (一对一):代替了 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。@One注解属性介绍:
标签, 是是多表查询的关键,在注解中用来指定子查询返回对象集合。使用格式:@Result(property=“”,column=“”,many=@Many(select=“”))用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户,一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

编写OrderMap.java
@Select("select *, o.id oid from orders o inner join user u on u.id = o.uid")
@Results({
@Result(column = "oid", property = "id"),
@Result(column = "ordertime", property = "orderTime"),
@Result(column = "total", property = "total"),
@Result(column = "uid", property = "user.id"),
@Result(column = "username", property = "user.username"),
@Result(column = "password", property = "user.password"),
@Result(column = "brithday", property = "user.brithday"),
})
List<Order> findOrderByUser();
对上述代码进行优化,添加相当于作用的功能:
@Select("select * from user where id = #{id}")
public User findById(long id);
@Select("select * from orders")
@Results({
@Result(column = "id", property = "id"),
@Result(column = "ordertime", property = "orderTime"),
@Result(column = "total", property = "total"),
@Result(
property = "user",//要封装的属性名称
column = "id",//根据那个字段去查询user表中的数据
javaType = User.class,//要封装的实体类型
//select属性 代表查询哪个接口的方法获取数据
one = @One(select = "com.zhxd.dao.UserMapper.findById")
)
})
List<Order> findOrderByUser();
测试结果:
@Test
public void findOrderByUser() {
List<Order> orderList = orderMapper.findOrderByUser();
for (Order order : orderList) {
System.out.println(order);
}
}

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户,用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

对应的sql语句:
select * from user
select * from orders where uid=查询出用户的id
@Select("select * from User")
@Results({
@Result(column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(column = "birthday", property = "birthday"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.zhxd.dao.OrderMapper.findByUid")
)
})
public List<User> findUserOrders();
@Select("select * from orders where uid = #{id}")
Order findByUid(long id);
@Test
public void testUserOrders() {
List<User> userList = mapper.findUserOrders();
for (User user : userList) {
System.out.println(user);
}
}

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用,多对多查询的需求:查询用户同时查询出该用户的所有角色

对应的sql语句:
select * from user;
select * from role r,user_role ur where r.id=ur.role_id and ur.user_id=用户的id
@Select("select * from user")
@Results({
@Result(column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(column = "birthday", property = "birthday"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many=@Many(select = "com.zhxd.dao.RoleMapper.findByUid")
)
})
public List<User> findUserRoles();
public interface RoleMapper {
@Select("select * from sys_user_role ur join sys_role r where ur.roleid = r.id and ur.userid=#{id}")
List<Role> findByUid(long id);
}
@Test
public void testUserRoles() {
List<User> userList = mapper.findUserRoles();
for (User user : userList) {
System.out.println(user);
}
}
