mybatis是一个优秀的持久层框架,它支持自定义sql,存储过程以及高级映射。其原型是ibatis,由Apache基金会收录后改名为mybatis
2.mybatis能做什么 Mybatis可以通过简单的XML或者注解来配置和映射原始类型,接口和java 实体类为数据库中的记录
3.为什么要用mybatis- 可以减少代码量 - 基于sql语句,简单易学 - 能了解底层组装过程(相对于hibernate) - SQL语句封装在配置文件中,便于统一维护和管理(当然注解也可代替配置文件),降低程序的耦合度 - 程序调试方便4.mybatis的使用 4.1 首先你得先有库有表
这里我先使用navicat创建了一些预先装备的数据,用于测试
4.2 新建一个java工程 这里我直接使用了maven,便于下载依赖
使用lombok方便测试时的字段修改重复改实体类的getset方法以及toString
4.3 编写数据库的表对应的实体类package com.demo.entity;
@Data
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
4.4 编写XML配置文件
这是官方文档的介绍,在配置文件方面官方文档的介绍很充足
而配置的顺序必须严格按照mybatis的规格写,否则会在编译时报错
----mybatis-config.xml4.5 编写映射文件(UserMapper.xml)
----UserMapper.xml4.6 编写测试类进行测试SELECT * FROM `mydata`.user;
package com.demo;
public class Demo1 {
public static void main(String[] args) throws IOException, SQLException {
// 获取文件流
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 获取sqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//
SqlSession sqlSession = factory.openSession();
List list = sqlSession.selectList("xxx.findAll");
System.out.println(list);
}
}
查询结果如下: [User(id=1, username=盛世名, birthday=null, sex=2, address=null), User(id=10, username=张甲吉, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=北京市), User(id=16, username=张吉东, birthday=null, sex=1, address=河南郑州), User(id=22, username=孙训, birthday=null, sex=1, address=河南郑州), User(id=24, username=周芷若, birthday=null, sex=1, address=河南郑州), User(id=25, username=赵敏, birthday=null, sex=1, address=河南郑州), User(id=26, username=小昭, birthday=null, sex=null, address=null)]
而我们的mybatis便可以正常使用了
5. 动态代理接口进行使用 上述的测试中,只是我们测试了mybatis是否正常的工作了,而在正式的使用中,我们的mybatis的映射文件会对应一个Dao层的接口,为其创建一个动态代理的对象,进行使用。而代理接口创建代理对象有以下几点需要注意:
-
mapper的命名空间(namespace)要对应接口的全限定类名(包括包路径和类名)
-
mapper的SQL语句标签如等 的ID需与接口的方法名相同
-
mapper的返回值类型ResultType或者ResultMap中的ResultType要与接口的返回值相同 或者 接口的返回值是集合时,与集合中的泛型相同
创建一个接口
package com.demo.dao; public interface UserDao { ListfindAll(); } 修改映射文件mapper
----UserMapper.xml
修改测试类进行测试
package com.demo; public class Demo1 { public static void main(String[] args) throws IOException, SQLException { // 获取文件流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); // 获取sqlSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); // SqlSession sqlSession = factory.openSession(); //获取动态代理对象 UserDao mapper = sqlSession.getMapper(UserDao.class); Listall = mapper.findAll(); System.out.println(all); } } [User(id=1, username=盛世名, birthday=null, sex=2, address=null), User(id=10, username=张甲吉, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=北京市), User(id=16, username=张吉东, birthday=null, sex=1, address=河南郑州), User(id=22, username=孙训, birthday=null, sex=1, address=河南郑州), User(id=24, username=周芷若, birthday=null, sex=1, address=河南郑州), User(id=25, username=赵敏, birthday=null, sex=1, address=河南郑州), User(id=26, username=小昭, birthday=null, sex=null, address=null)] Process finished with exit code 0
同样可以获取结果,到此动态代理成功
关于参数的使用有几种方式,分两大类进行讨论。而映射文件中编写的parameterType可以省略不写
6.1 单个参数 单个参数时,如果参数是基本类型或者字符串,我们可以不写任何注解,在SQL语句中使用${参数名}或者#{参数名}接收参数的值。
而#{}代表的是占位符,优于sql性能的提升和安全(SQL注入问题),所以大多数情况下使用
${}代表的是字符串的拼接,极少数情况才会用到
写个例子
#UserDao
public interface UserDao {
List findAll();
User findOne(Integer id);
}
#Test
UserDao mapper = sqlSession.getMapper(UserDao.class);
User one = mapper.findOne(10);
System.out.println(one);
//User(id=10, username=张甲吉, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=北京市)
正常使用
6.2 多参数的接收 多个参数接收的方法有多种
-
封装好的实体类,传入实体类时直接使用实体类中的属性值即可,但是传入的实体类必须只能有一个
User user = new User(); user.setUsername("张甲吉"); user.setId(10); User one = mapper.findOneByUser(user); System.out.println(one);
-
使用Map将多参数传入
Map
map = new HashMap<>(); map.put("username","张甲吉"); map.put("id",10); User one = mapper.findOneByMap(map); System.out.println(one); -
使用注解@Param(“xxx”)修饰参数,在映射文件SQL语句中使用#{xxx}或${xxx}进行接收
#Dao public interface UserDao { User findOneByParameters(@Param("id") Integer id,@Param("usr") String username); } #Test User one = mapper.findOneByParameters(10,"张甲吉"); System.out.println(one); -
在映射文件中使用#{param1},#{param2},#{param3}…或者#{arg0},#{arg1},#{arg2},按顺位接收,注意param从1开始,arg从0开始。但是这两种方法都不推荐使用,因为容易语义不够明确容易混淆,后期的维护修改等容易出现歧义
值得一提的是,在使用了@param注解后,arg将无法使用,而param则是可以继续使用
#Dao public interface UserDao { User findOneByParameters(Integer id, String username); } -
如果传入的是多个封装类,那么可以使用“.”来获取其属性
#Dao public interface UserDao { User findOneByTest(User user,Map map); } #Test User user = new User(); user.setUsername("张甲吉"); user.setId(10); Mapmap = new HashMap<>(); map.put("username","张甲吉"); map.put("id",10); User one = mapper.findOneByTest(user,map); System.out.println(one);
多表查询使用了resultMap
其中resultMap中的标签有等
PS:其中要注意的是,标签的顺序问题,如果顺序打乱会报错,关于顺序可以在官网也可以查看,具体如下
resultMap标签中可以使用extends继承,继承别的XML配置中的resultMap要编写对方mapper的命名空间.resultMapID
resultMap标签中还可以使用AutoMapping开启自动映射,基础类型的列名和属性名相同是可以不再编写result,这个自动映射其实也可以在配置文件中开启,而后如果不想开启则需要单独为resultMap中的AutoMapping赋值False 。值得一提的是在resultMap也就是父标签中开启AutoMapping是不会影响子标签如的,如果子标签需要开启要在标签的属性AutoMapping中指定ture,全局默认开启时需要关闭也是同理
association和collection标签可以使用select标签指定子查询,子查询的列名传递使用colunm属性标签,可以开启懒加载,而这两个在对应实体类的引用类型是注意一个是javaType一个是ofType。
discriminator标签目前用得比较少,暂时没有过多的讨论



