java之mybatis的使用

【java之mybatis的使用】mybatis文档:http://www.mybatis.cn/archives/789.html
http://www.mybatis.cn/archives/920.html
参考:https://blog.csdn.net/u012702547/article/details/88643598
https://www.cnblogs.com/stars-one/p/11537439.html
Mybatis的功能架构分为三层:
(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

MyBatis的初始化,会从mybatis-config.xml配置文件,解析构造成Configuration这个类。

//// // //

也可以在application.properties中直接配置数据库相关信息;
spring.datasource.url = jdbc:mysql://localhost:3306/firstDB spring.datasource.username = root spring.datasource.password = 1234567890

(1)加载配置:配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
(2)SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。
(3)SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
(4)结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。
如果需要用到Mapper.xml配置sql的话就需要在application.yml配置中的 mybatis中将 mapper-locations: classpath:/mapper/*.xml 配置出来, 但是要记住mapper前面要用“/”隔开而不是 “ .”而且Mapper.xml要放在 resources 下面。 如果是在dao接口类中使用@Select,@Update等增删改查的注解的话, 在 yml配置中就不需要 mapper-locations的配置。#mybatis.mapper-locations=classpath:com/example/demo/*.xml是寻找mapper.xml的位置; #mybatis.type-aliases-package=com.example.demo.entity是扫描mapper.xml中resultType返回的实体类所在的包.

**xml方式添加映射文件
什么是resultMap?
在mybatis中有一个resultMap标签,它是为了映射select查询出来结果的集合,其主要作用是将实体类中的字段与数据库表中的字段进行关联映射。
当实体类中的字段与数据库表中的字段相同时,可以将resultMap标签中的关联关系忽略不写。
当实体类中的字段与数据库表中的字段不相同时,就需要在resultMap标签中将实体类字段与数据库字段一 一进行关联映射,或者开启驼峰规则,让它自动转换。
**如果实体类中和数据库中的字段完全一致,则可以用resultType;
**如果数据库中字段采用下划线的方式,可以在mybatis中开启驼峰命名,
https://blog.csdn.net/ITBigGod/article/details/82685918
**resultType:指的是数据库操作后返回的数据类型.
在XML中写SQL,例如创建一个UserMapper,如下:public interface UserMapper { List getAllUser(); Integer addUser(User user); Integer updateUserById(User user); Integer deleteUserById(Integer id); }创建UserMapper.xml文件,如下: select * from t_user; insert into user (username,address) values (#{username},#{address}); update user set username=#{username},address=#{address} where id=#{id} delete from user where id=#{id}

**注解方式添加映射
MyBatis就可以创建Mapper来使用了,直接创建一个UserMapper2,如下: @Mapper public interface UserMapper2 { @Select("select * from user") List getAllUsers(); @Results({ @Result(property = "id", column = "id"), @Result(property = "username", column = "u"), @Result(property = "address", column = "a") }) @Select("select username as u,address as a,id as id from user where id=#{id}") User getUserById(Long id); @Select("select * from user where username like concat('%',#{name},'%')") List getUsersByName(String name); @Insert({"insert into user(username,address) values(#{username},#{address})"}) @SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Integer.class) Integer addUser(User user); @Update("update user set username=#{username},address=#{address} where id=#{id}") Integer updateUserById(User user); @Delete("delete from user where id=#{id}") Integer deleteUserById(Integer id); }这里是通过全注解的方式来写SQL,不写XML文件,@Select、@Insert、@Update以及@Delete四个注解分别对应XML中的select、insert、update以及delete标签,@Results注解类似于XML中的ResultMap映射文件(getUserById方法给查询结果的字段取别名主要是向小伙伴们演示下@Results注解的用法),另外使用@SelectKey注解可以实现主键回填的功能,即当数据插入成功后,插入成功的数据id会赋值到user对象的id属性上。


Mybatis的配置文件一共由两类:
一类用于指定数据源、事务属性以及其他一些参数配置信息(通常是一个独立的文件,可以称之为全局配置文件,比如:mybatis-config.xml);
另一类则用于 指定数据库表和程序之间的映射信息(可能不止一个文件,我们称之为映射文件),比如mymapper.xml.
public class Test1 {public static void main(String[] args) throws IOException { //mybatis的配置文件 String resource = "conf.xml"; //使用类加载器加载mybatis的配置文件(它也加载关联的映射文件) InputStream is = Test1.class.getClassLoader().getResourceAsStream(resource); //构建sqlSession的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is); //使用MyBatis提供的Resources类加载mybatis的配置文件(它也加载关联的映射文件) //Reader reader = Resources.getResourceAsReader(resource); //构建sqlSession的工厂 //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //创建能执行映射文件中sql的sqlSession SqlSession session = sessionFactory.openSession(); /** * 映射sql的标识字符串, * me.gacl.mapping.userMapper是userMapper.xml文件中mapper标签的namespace属性的值, * getUser是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL */ String statement = "me.gacl.mapping.userMapper.getUser"; //映射sql的标识字符串 //执行查询返回一个唯一user对象的sql User user = session.selectOne(statement, 1); System.out.println(user); } }通过跟踪源代码可以看到SqlSession通过mapper映射的id来查找数据的方法;

MappedStatement与Mapper.xml配置文件中的一个select/update/insert/delete节点相对应。mapper中配置的标签都被封装到了此对象中,主要用途是描述一条SQL语句。
加载配置文件的过程中,会对mybatis-config.xml中的各个标签都进行解析,其中有 mappers标签用来引入mapper.xml文件或者配置mapper接口的目录。

SqlSessionFactoryBuilder根据传入的数据流(XML)生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例。
SqlSessionFactory的主要功能是创建SqlSession对象;
SqlSession对象的主要功能是完成一次数据库的访问和结果的映射,它类似于数据库的session概念,由于不是线程安全的,所以SqlSession对象的作用域需限制方法内。SqlSession的默认实现类是DefaultSqlSession,它有两个必须配置的属性:Configuration和Executor。SqlSession对数据库的操作都是通过Executor来完成的。
SqlSession :默认创建DefaultSqlSession 并且开启一级缓存,创建执行器 、赋值。
Executor对象在创建Configuration对象的时候创建,并且缓存在Configuration对象里。Executor对象的主要功能是调用StatementHandler访问数据库,并将查询结果存入缓存中(如果配置了缓存的话)。
StatementHandler是真正访问数据库的地方,并调用ResultSetHandler处理查询结果。
***mybatis几种实现方式:
参考:https://blog.csdn.net/weixin_42249629/article/details/81677056
非注解的情况,需要配置mybatis-config.xml和mapper.xml的实体映射; 注解的情况下,只需要在application.properties中配置数据库的资源就行,其他的.xml文件不用配置,程序启动自动加载mybatis-config.xml文件.
Mybatis 的Mapper 是指Mybatis 执行数据库操作的接口类以及方法,在非注解模式下,还包含与类对应的 xml 配置文件。
下面是使用配置文件的方式实现:
@SpringBootApplication @MapperScan(basePackages = "com.example.demo") public class MybatisplusdemoApplication { // SqlSessionFactory sqlSessionFactory; public static void main(String[] args) throws IOException { SpringApplication.run(MybatisplusdemoApplication.class, args); InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession sqlsession = sqlSessionFactory.openSession(); /* * 方式一 * */ //参数是mapper.xml中的,第一个参数找到执行的SQL,命名空间加上sql的id第二个参数是sql语句的条件 //Goods goods= sqlsession.selectOne("com.example.demo.GoodsMapper.selectGoods",1); //List goods= sqlsession.selectList("com.example.demo.GoodsMapper.selectGoods"); //List goods= sqlsession.selectList("com.example.demo.GoodsMapper.selectGoods",1); //System.out.println(goods.get(0).getPrice()); /* * 方式二 * * */ //mapper接口和GoodsMapper映射文件关联 GoodsMapper mapper=sqlsession.getMapper(GoodsMapper.class); List goods=mapper.selectGoods(); System.out.println(goods.get(0).getWeight()); /* * 方式三 * 注解的方式 * */ //mapper接口和GoodsMapper映射文件关联,通过反射得到对象 // OrdersMapper mapper=sqlsession.getMapper(OrdersMapper.class); //List orders=mapper.selectOrders(); //System.out.println(orders.get(0)); sqlsession.close(); }}***GoodsMapper.xml select * from Goods ***mybatis-config ***GoodsMapper.javapackage com.example.demo; import java.util.List; public interface GoodsMapper { public List selectGoods(); }***GoodsMapperIm.javapublic class GoodsMapperIm implements GoodsMapper { private SqlSessionFactory factory; //覆盖掉默认构造函数,这样就有了工厂,可以进一步创建对象 public GoodsMapperIm(SqlSessionFactory factory){ this.factory = factory; } @Override public List selectGoods() { //1.使用工厂创建SqlSession对象 SqlSession sqlSession = factory.openSession(); //2.使用sqlSession执行查询所有方法(此处需要的参数:(String statement)从配置文件中获取) namespace + id List userList = sqlSession.selectList("com.example.demo.GoodsMapper.selectGoods"); //使用完后关闭掉 sqlSession.close(); return userList; } }

**使用注解的方式实现mybatis
mybatis注解方式传递参数的几种方式:http://www.mybatis.cn/archives/920.html
** OrdersController@RestController public class OrdersController { @Autowired private OrdersServicer ordersServicer; //使用对象的方式传递参数 @RequestMapping("/addorders") public Integer addOrder() { Orders orders= new Orders(3, "003", 3,"1","1", new Date()); return ordersServicer.addOrder(orders); } @RequestMapping("/updateOrdersById/{orderprice}/{id}") publicInteger updateOrdersById(@PathVariable double orderprice,@PathVariable int id) { return ordersServicer.updateOrdersById(orderprice,id); }//利用map传递参数 @RequestMapping("/updateOrdersByIdmap") publicInteger updateOrdersByIdmap() { Map updateMap=new HashMap(); updateMap.put("orderprice", 8); updateMap.put("id", 8); return ordersServicer.updateOrdersByIdmap(updateMap); }@RequestMapping("/deleteOrdersById/{id}") publicInteger deleteOrdersById(@PathVariable int id) { return ordersServicer.deleteOrdersById(id); } @RequestMapping("/selectorders/{ids}") public List selectOrders(@PathVariable int ids) { return ordersServicer.selectOrders(ids); }}** Orderspublic class Orders { private Integer id; private String ordernum; privatedouble orderprice; private Date ordercreatetime; public Stringorderispay; public String orderissender; public String getOrderissender() { return orderissender; } public void setOrderissender(String orderissender) { this.orderissender = orderissender; } public String getOrderispay() { return orderispay; } public void setOrderispay(String orderispay) { this.orderispay = orderispay; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOrdernum() { return ordernum; } public void setOrdernum(String ordernum) { this.ordernum = ordernum; } public double getOrderprice() { return orderprice; } public void setOrderprice(double orderprice) { this.orderprice = orderprice; } public Date getOrdercreatetime() { return ordercreatetime; } public void setOrdercreatetime(Date ordercreatetime) { this.ordercreatetime = ordercreatetime; }public Orders(Integer id, String ordernum, double orderprice,Stringorderispay, String orderissender,Date ordercreatetime) { super(); this.id = id; this.ordernum = ordernum; this.orderprice = orderprice; this.ordercreatetime = ordercreatetime; this.orderispay=orderispay; this.orderissender=orderissender; }}** OrdersServicerpublic interface OrdersServicer {Integer addOrder(Orders orders); Integer updateOrdersById(double orderprice,Integer id); Integer updateOrdersByIdmap(Map updateMap); Integer deleteOrdersById(Integer id); public List selectOrders(int ids); }** OrdersServicerIm@Service public class OrdersServicerIm implements OrdersServicer{ @Autowired private OrdersMapper ordersMapper; @Override public Integer addOrder(Orders orders) {return ordersMapper.addOrder(orders); } @Override public Integer updateOrdersById(double orderprice,Integer id) {return ordersMapper.updateOrdersById(orderprice, id); } @Override publicInteger updateOrdersByIdmap(Map updateMap) { return ordersMapper.updateOrdersByIdmap(updateMap); } @Override publicInteger deleteOrdersById(Integer id){return ordersMapper.deleteOrdersById(id); } @Override public List selectOrders(int idss) { return ordersMapper.selectOrders(idss); }}** OrdersMapper @Mapper public interface OrdersMapper { @Insert({"insert into orders(ordernum,orderprice,orderispay,orderissender,ordercreatetime) values(#{ordernum},#{orderprice},#{orderispay},#{orderissender},#{ordercreatetime})"}) //@SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Integer.class) Integer addOrder(Orders orders); @Update("update orders set orderprice=#{orderprice} where id=#{id}") Integer updateOrdersById(double orderprice,Integer id); @Update("update orders set orderprice=#{orderprice} where id=#{id}") Integer updateOrdersByIdmap(Map updateMap); @Delete("delete from orders where id=#{id}") Integer deleteOrdersById(Integer id); @Select(value ="https://www.it610.com/article/select *from Orders where id=#{ids}") public List selectOrders(int ids); }

***mybatis代码生成器
参考:https://www.cnblogs.com/throwable/p/12046848.html
代码生成器的使用步骤:
**在pom.xml中添加以来和配置
org.mybatis.generator mybatis-generator-maven-plugin 1.4.0 ${basedir}/src/main/resources/generatorConfig.xml true true mysql mysql-connector-java

**创建generatorConfig.xml文件

**安装mybatis-gennerator插件:eclipse中help-》eclipse marketplace
运行mybatis生成器有四种方法,这里只使用mybatis-generator插件;
***若是使用注解的方式需要做一些更改:
在pom.xml中引入:
org.mybatis.dynamic-sql mybatis-dynamic-sql 1.1.4

generatorConfig.xml中还需要修改:


***@Provider的使用方式https://www.cnblogs.com/yadongliang/p/13346494.html


***mybaits中常见问题:
*同一个 方法在xml里有映射,同时又有注解的方式解析,这样会冲突报错.

    推荐阅读