简介 1 Mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程;Mybatis可以通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,mybatis框架执行sql并将结果映射为java对象并返回;采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作
Mybatis官网
原始JDBC操作
数据库中的user表
列名
数据类型
id
int
name
int
birthday
bigint
创建User实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class User { private Integer id; private Integer name; private Date birthday; public User () {} public User (Integer id, Integer name) { this .id = id; this .name = name; } public User (Integer id, Integer name, Date birthday) { this .id = id; this .name = name; this .birthday = birthday; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public Integer getName () { return name; } public void setName (Integer name) { this .name = name; } public Date getBirthday () { return birthday; } public void setBirthday (Date birthday) { this .birthday = birthday; } @Override public String toString () { return "id=" + id + ", name=" + name + ", birthday=" + birthday; } }
查询数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public static void main (String[] args) throws SQLException { Connection connection = DriverManager.getConnection("jdbc:mysql:///mysqltest?serverTimezone=UTC" , "root" , "root" ); PreparedStatement statement = connection.prepareStatement("select * from user" ); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()){ User user = new User(); user.setId(resultSet.getInt("id" )); user.setName(resultSet.getInt("name" )); System.out.println(user); } resultSet.close(); statement.close(); connection.close(); }
插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public static void main (String[] args) throws SQLException, ClassNotFoundException { User user = new User(); user.setId(10 ); user.setName(123 ); Class.forName("com.mysql.cj.jdbc.Driver" ); Connection connection = DriverManager.getConnection("jdbc:mysql:///mysqltest?serverTimezone=UTC" , "root" , "root" ); PreparedStatement statement = connection.prepareStatement("insert into user values (?, ?)" ); statement.setInt(1 ,user.getId()); statement.setInt(2 ,user.getName()); statement.executeUpdate(); statement.close(); connection.close(); }
使用原始jdbc开发存在的问题 1 2 3 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能 sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码 查询操作时,需要手动将结果集中的数据手动封装到实体中;插入操作时,需要手动将实体的数据设置到sql语句的占位符位置
解决方法 1 2 3 使用数据库连接池初始化连接资源 将sql语句抽取到xml配置文件中 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射
使用Mybatis操作 开发步骤 1 2 3 4 5 6 添加MyBatis的坐标 创建user数据表 编写User实体类 编写映射文件UserMapper.xml 编写核心文件SqlMapConfig.xml 编写测试类
导入要使用的坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.4.5</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.6</version > <scope > runtime</scope > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > test</scope > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.12</version > </dependency >
编写UserMapper.xml映射文件,需要同实体类所在的包一致;如:如果实体类在java的com.example.demo下,那么mapper映射文件就应该在resources的com.example.demo下进行创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?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 ="userMapper" > <select id ="findAll" resultType ="User" > select * from user </select > <insert id ="add" parameterType ="com.example.demo.User" > insert into user values(#{id},#{name}) </insert > <update id ="update" parameterType ="com.example.demo.User" > update user set id = #{id} where name = #{name} </update > <delete id ="delete" parameterType ="java.lang.Integer" > delete from user where id=#{id} </delete > </mapper >
编写MyBatis核心文件(sqlMapConfig.xml),在resources下进行创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <?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 > <properties resource ="jdbc.properties" /> <typeAliases > <typeAlias type ="com.example.demo.User" alias ="User" /> </typeAliases > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="org/mybatis/example/BlogMapper.xml" /> </mappers > </configuration >
编写测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @Test public void contextLoads () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = sqlSession.selectList("userMapper.findAll" ); System.out.println(userList); int insert = sqlSession.insert("userMapper.add" , new User(12 ,46 )); System.out.println(insert); int update = sqlSession.update("userMapper.update" , new User(15 , 123 )); System.out.println(update); int delete = sqlSession.delete("userMapper.delete" , 9 ); System.out.println(delete); sqlSession.commit(); sqlSession.close(); }
MyBatis核心配置文件层级关系
MyBatis常用别名
别名
数据类型
string
String
long
Long
int
Integer
double
Double
boolean
Boolean
MyBatis相应API SqlSession工厂构建器SqlSessionFactoryBuilder
常用API:SqlSessionFactory build(InputStream inputStream)
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
1 2 3 4 5 6 7 String resource = "org/mybatis/builder/mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream);
Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个web URL中加载资源文件
SqlSession工厂对象SqlSessionFactory SqlSessionFactory常用的创建SqlSession实例的方法
方法
解释
openSession()
会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交该事务,更新操作数据才会持久化到数据库中
openSession(boolean autoCommit)
参数为是否自动提交,如果设置为true,就不需要手动提交事务
SqlSession会话对象
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法
1 2 3 4 5 6 执行语句的方法主要有: <T> T selectOne (String statement, Object parameter) <E> List<E> selectList (String statement, Object parameter) int insert (String statement, Object parameter) int update (String statement, Object parameter) int delete (String statement, Object parameter)
操作事务的方法主要有:
1 2 void commit () void rollback ()
Mybatis的Dao层实现 传统开发方式
编写UserDao接口
1 2 3 public interface UserDao { List<User> findAll () throws IOException ; }
编写UserDaoImpl实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public List<User> findAll () throws Exception { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = sqlSession.selectList("userMapper.findAll" ); sqlSession.close(); return userList; }
测试代码
1 2 3 4 5 6 7 8 9 @Test public void testTraditionDao () throws IOException { UserDao userDao = new UserDaoImpl(); List<User> all = userDao.findAll(); System.out.println(all); }
代理开发方式
Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法
Mapper 接口开发需要遵循的规范 1 2 3 4 Mapper.xml文件中的namespace与mapper接口的全限定名相同 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
编写UserMapper接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public interface UserMapper { List<User> findAll () ; Integer add (User user) ; }
编写UserMapper配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?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.example.demo.UserMapper" > <select id ="findAll" resultType ="com.example.demo.User" > select * from user </select > <insert id ="add" parameterType ="com.example.demo.User" > insert into user values(#{id},#{name}) </insert > </mapper >
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Test public void testProxyDao () throws Exception { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> users = userMapper.findAll(); System.out.println(users); Integer add = userMapper.add(new User(123 , 5 )); System.out.println(add); sqlSession.commit(); sqlSession.close(); }
MyBatis映射文件深入 动态sql语句
Mybatis 的映射文件中,有些时候业务逻辑复杂时,SQL是需要动态变化的,而之前的 SQL 就不能满足业务要求
if
UserMapper.xml配置文件: 根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如如果name不为空时要加入id作为条件
1 2 3 4 5 6 7 8 9 10 11 <select id ="findByCondition" parameterType ="user" resultType ="user" > select * from User <where > <if test ="id != 0 and id != null" > and id=#{id} </if > <if test ="name != 0 and name!=null" > and name=#{name} </if > </where > </select >
UserMapper
1 User findByCondition (User user) ;
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void findByCondition () throws Exception { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; User user1 = new User(); user1.setName(123 ); User user = userMapper.findByCondition(user1); System.out.println(user); }
foreach
配置文件: 循环执行sql的拼接操作;例如:select * from user where id in (1,2,5)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <select id ="findByIds" parameterType ="list" resultType ="com.example.demo.User" > select * from user <where > <foreach collection ="list" open ="id in(" close =")" item ="id" separator ="," > #{id} </foreach > </where > </select >
UserMapper
1 List<User> findByIds (List<Integer> list) ;
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Test public void findByIds () throws Exception { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; ArrayList<Integer> list = new ArrayList(); list.add(1 ); list.add(2 ); list.add(3 ); List<User> users = userMapper.findByIds(list); System.out.println(users); }
SQL片段抽取
可将映射文件中重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?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.example.demo.UserMapper" > <sql id ="selectUser" > select * from user</sql > <select id ="findAll" resultType ="com.example.demo.User" > <include refid ="selectUser" /> </select > <select id ="findByCondition" parameterType ="com.example.demo.User" resultType ="com.example.demo.User" > <include refid ="selectUser" /> <where > <if test ="id != 0 and id != null" > and id=#{id} </if > <if test ="name != 0 and name != null" > and name=#{name} </if > </where > </select > <select id ="findByIds" parameterType ="list" resultType ="com.example.demo.User" > <include refid ="selectUser" /> <where > <foreach collection ="list" open ="id in(" close =")" item ="id" separator ="," > #{id} </foreach > </where > </select > </mapper >
MyBatis核心配置文件深入 typeHandlers标签
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分)
类型处理器
Java类型
JDBC类型
BooleanTypeHandler
java.lang.Boolean,boolean
数据库兼容的BOOLEAN
ByteTypeHandler
java.lang.Byte,byte
数据库兼容的NUMERIC或BYTE
ShortTypeHandler
java.lang.Short,short
数据库兼容的NUMERIC或SHORT INTEGER
IntegerTypeHandler
java.lang.Integer,int
数据库兼容的NUMERIC或INTEGER
LongTypeHandler
java.lang.Long,long
数据库兼容的NUMERIC或LONG INTEGER
可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口,或继承一个很便利的类org.apache.ibatis.type.BaseTypeHandler,然后可以选择性地将它映射到一个JDBC类型。例如需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换
数据表: 改变表,增加列birthday,数据类型为bigint
创建DateTypeHandler类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class DateTypeHandler extends BaseTypeHandler <Date > { public void setNonNullParameter (PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException { preparedStatement.setLong(i, date.getTime()); } public Date getNullableResult (ResultSet resultSet, String s) throws SQLException { long aLong = resultSet.getLong(s); return new Date(aLong); } public Date getNullableResult (ResultSet resultSet, int i) throws SQLException { long aLong = resultSet.getLong(i); return new Date(aLong); } public Date getNullableResult (CallableStatement callableStatement, int i) throws SQLException { long aLong = callableStatement.getLong(i); return new Date(aLong); } }
在Mybatis核心配置文件中注册自定义类型处理器
1 2 3 4 <typeHandlers > <typeHandler handler ="com.example.demo.DateTypeHandler" /> </typeHandlers >
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void save () throws Exception { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; userMapper.save(new User(154 , 111 , new Date())); sqlSession.close(); }
数据库存储后的图
plugins标签
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
在pom.xml中导入通用PageHelper坐标
1 2 3 4 5 6 7 8 9 10 11 <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 3.7.5</version > </dependency > <dependency > <groupId > com.github.jsqlparser</groupId > <artifactId > jsqlparser</artifactId > <version > 0.9.1</version > </dependency >
在Mybatis核心配置文件中配置PageHelper插件
1 2 3 4 5 6 7 <plugins > <plugin interceptor ="com.github.pagehelper.PageHelper" > <property name ="dialect" value ="mysql" /> </plugin > </plugins >
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Test public void testPageHelper () throws Exception { PageHelper.startPage(2 ,2 ); InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> userList = userMapper.findAll(); for (User user : userList) { System.out.println(user); } PageInfo<User> pageInfo = new PageInfo<User>(userList); System.out.println("上一页:" +pageInfo.getPrePage()); System.out.println("下一页:" +pageInfo.getNextPage()); System.out.println("总条数:" +pageInfo.getTotal()); System.out.println("总页数:" +pageInfo.getPages()); System.out.println("当前页:" +pageInfo.getPageNum()); System.out.println("每页显示长度:" +pageInfo.getPageSize()); System.out.println("是否第一页:" +pageInfo.isIsFirstPage()); System.out.println("是否最后一页:" +pageInfo.isIsLastPage()); sqlSession.close(); }
核心配置文件详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 <?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 > <properties resource ="jdbc.properties" /> <typeAliases > <typeAlias type ="com.example.demo.User" alias ="User" /> </typeAliases > <typeHandlers > <typeHandler handler ="com.example.demo.DateTypeHandler" /> </typeHandlers > <plugins > <plugin interceptor ="com.github.pagehelper.PageHelper" > <property name ="dialect" value ="mysql" /> </plugin > </plugins > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="org/mybatis/example/BlogMapper.xml" /> </mappers > </configuration >
多表操作
数据库中的orders表
列名
数据类型
id
int
orderTime
varchar
total
double
一对一
创建Order实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class Order { private Integer id; private Date orderTime; private Double total; private User user; public Integer getId () { return id; } public void setId (Integer 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; } public Order () { } public Order (Integer id, Date orderTime, Double total, User user) { this .id = id; this .orderTime = orderTime; this .total = total; this .user = user; } @Override public String toString () { return "Order{" + "id=" + id + ", orderTime=" + orderTime + ", total=" + total + ", user{" + user + "}}" ; } }
创建OrderMapper接口
1 2 3 4 5 public interface OrderMapper { List<Order> findAll () ; }
创建OrderMapper.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <?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.example.demo.OrderMapper" > <resultMap id ="orderMap" type ="com.example.demo.Order" > <id column ="id" property ="id" /> <result column ="orderTime" property ="orderTime" /> <result column ="total" property ="total" /> <result column ="uid" property ="user.id" /> <result column ="name" property ="user.name" /> <result column ="birthday" property ="user.birthday" /> </resultMap > <select id ="findAll" resultMap ="orderMap" > select *, u.id uid from orders o, user u where o.uid = u.id </select > </mapper >
在Mybatis核心配置文件中的mappers下引入映射文件
1 <mapper resource ="com/example/demo/OrderMapper.xml" />
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void orderTest () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class ) ; List<Order> orderList = orderMapper.findAll(); for (Order order : orderList) { System.out.println(order); } sqlSession.close(); }
一对多
User实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class User { private List<Order> orderList; public User (Integer id, Integer name, Date birthday, List<Order> orderList) { this .id = id; this .name = name; this .birthday = birthday; this .orderList = orderList; } public List<Order> getOrder () { return orderList; } public void setOrder (List<Order> orderList) { this .orderList = orderList; } @Override public String toString () { return "User{" + "id=" + id + ", name=" + name + ", birthday=" + birthday + ", orderList{" + orderList + "}}" ; } }
UserMapper接口
1 List<User> findAllUserAndOrder () ;
UserMapper.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <resultMap id ="userMap" type ="com.example.demo.User" > <id column ="id" property ="id" /> <result column ="name" property ="name" /> <result column ="birthday" property ="birthday" /> <collection property ="orderList" ofType ="com.example.demo.Order" > <id column ="oid" property ="id" /> <result column ="orderTime" property ="orderTime" /> <result column ="total" property ="total" /> <result column ="uid" property ="uid" /> </collection > </resultMap > <select id ="findAllUserAndOrder" resultMap ="userMap" > select *, o.id oid from user u, orders o where u.id = o.uid </select >
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void userTest () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> userList = userMapper.findAllUserAndOrder(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
多对多
数据库中的role表
列名
数据类型
id
int
name
varchar
数据库中的user_role表
列名
数据类型
userId
int
roleId
int
数据库中的role表
列名
数据类型
id
int
rname
varchar
创建Role实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Role { private Integer id; private String name; 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; } public Role () { } public Role (Integer id, String name) { this .id = id; this .name = name; } @Override public String toString () { return "Role{" + "id=" + id + ", name='" + name + '\'' + '}' ; } }
User实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 private List<Role> roleList;public User (Integer id, Integer name, Date birthday, List<Role> roleList) { this .id = id; this .name = name; this .birthday = birthday; this .roleList = roleList; } public List<Role> getRoleList () { return roleList; } public void setRoleList (List<Role> roleList) { this .roleList = roleList; } @Override public String toString () { return "User{" + "id=" + id + ", name=" + name + ", birthday=" + birthday + ", roleList{" + roleList + "}}" ; }
UserMapper接口
1 List<User> findAllUserAndRole () ;
UserMapper.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 <resultMap id ="userAndRoleMap" type ="com.example.demo.User" > <id column ="id" property ="id" /> <result column ="name" property ="name" /> <result column ="birthday" property ="birthday" /> <collection property ="roleList" ofType ="com.example.demo.Role" > <id column ="roleId" property ="id" /> <id column ="rname" property ="name" /> </collection > </resultMap > <select id ="findAllUserAndRole" resultMap ="userAndRoleMap" > select * from user u, user_role ur, role r where u.id = ur.userId and r.id = ur.roleId </select >
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void userAndRoleTest () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> userList = userMapper.findAllUserAndRole(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
注解开发
新建一个项目,导入实体类,DateTypeHandler,mapper接口,sqlMapConfig.xml核心配置文件,若数据源环境使用了配置文件,再将jdbc.properties配置文件导入
Mybatis常用注解
注解
作用
说明
@Insert
新增
@Update
更新
@Delete
删除
@Select
查询
@Result
结果集封装
代替id和result标签,属性:column:数据库的列名,property:需要装配的属性名,one:需要使用@One注解,many:需要使用@Many注解
@Results
封装多个结果集,与@Result一起使用
代替resultMap标签,使用格式@Results({@Result(), @Result()})或@Results(@Result())
@One
一对一结果集封装
代替association标签,使用格式:@Result(column=””, property=””,one=@One(select=””)),select:指定用来多表查询的mapper
@Many
一对多结果集封装
代替collection标签,使用格式:@Result(column=””, property=””, many=@Many(select=””))
使用注解进行单表的增删改查
sqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 <typeHandlers > <typeHandler handler ="com.example.test.DateTypeHandler" /> </typeHandlers > <mappers > <package name ="com.example.test" /> </mappers >
UserMapper接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public interface UserMapper { @Insert ("insert into user values(#{id},#{name},#{birthday})" ) void save (User user) ; @Update ("update user set name = #{name} where id = #{id}" ) void update (User user) ; @Delete ("delete from user where id = #{id}" ) void delete (Integer id) ; @Select ("select * from user where id = #{id}" ) User findById (Integer id) ; @Select ("select * from user" ) List<User> findAll () ; }
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public class AnnotationTest { private UserMapper userMapper; private SqlSession sqlSession; @Before public void before () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); sqlSession = sqlSessionFactory.openSession(true ); userMapper = sqlSession.getMapper(UserMapper.class ) ; } @Test public void testSave () { userMapper.save(new User(1231 ,1231 , new Date())); sqlSession.close(); } @Test public void testUpdate () { userMapper.update(new User(1 ,75 )); sqlSession.close(); } @Test public void testDelete () { userMapper.delete(5 ); sqlSession.close(); } @Test public void testFindById () { System.out.println(userMapper.findById(1 )); sqlSession.close(); } @Test public void testFindAll () { List<User> userList = userMapper.findAll(); for (User user : userList) { System.out.println(user); } sqlSession.close(); } }
一对一注解开发
OrderMapper接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @Select ("select *, u.id uid from orders o, user u where o.uid = u.id" )@Results ({ @Result (column = "id" , property = "id" ), @Result (column = "orderTime" , property = "orderTime" ), @Result (column = "total" , property = "total" ), @Result (column = "uid" , property = "user.id" ), @Result (column = "name" , property = "user.name" ), @Result (column = "birthday" , property = "user.birthday" ) }) List<Order> findAll () ;@Select ("select * from orders" )@Results ({ @Result (column = "id" , property = "id" ), @Result (column = "orderTime" , property = "orderTime" ), @Result (column = "total" , property = "total" ), @Result ( column = "uid" , property = "user" , javaType = User.class , /* select属性: 使用指定接口下的方法获得数据 */ one = @One (select = "com.example.test.UserMapper.findById" ) ) }) List<Order> findAll () ;
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void testFindAllOrder () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class ) ; List<Order> orderList = orderMapper.findAll(); for (Order order : orderList) { System.out.println(order); } sqlSession.close(); }
一对多注解开发
OrderMapper接口
1 2 @Select ("select * from orders where uid = #{uid}" )List<Order> findById (Integer uid) ;
UserMapper接口
1 2 3 4 5 6 7 8 9 10 11 12 13 @Select ("select * from user" )@Results ({ @Result (id = true , column = "id" , property = "id" ), @Result (column = "name" , property = "name" ), @Result (column = "birthday" , property = "birthday" ), @Result ( column = "id" , javaType = List.class , property = "orderList" , many = @Many (select = "com.example.test.OrderMapper.findById" ) ) }) List<User> findAllUserAndOrder () ;
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void testFindAllUserAndOrder () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> userList = userMapper.findAllUserAndOrder(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
多对多注解开发
RoleMapper接口
1 2 @Select ("select * from role r, user_role ur where ur.roleId = r.id and ur.userId = #{uid}" )List<Role> findById (Integer uid) ;
UserMapper接口
1 2 3 4 5 6 7 8 9 10 11 12 13 @Select ("select * from user" )@Results ({ @Result (id = true , column = "id" , property = "id" ), @Result (column = "name" , property = "name" ), @Result (column = "birthday" , property = "birthday" ), @Result ( column = "id" , javaType = List.class , property = "roleList" , many = @Many (select = "com.example.test.RoleMapper.findById" ) ) }) List<User> findAllUserAndRole () ;
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void testFindAllUserAndRole () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(true ); UserMapper userMapper = sqlSession.getMapper(UserMapper.class ) ; List<User> userList = userMapper.findAllUserAndRole(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }