首页 > 其他分享 >MyBatis(国税)

MyBatis(国税)

时间:2023-01-12 17:31:54浏览次数:57  
标签:mapper public mybatis book MyBatis import 国税 id

一、MyBatis概要

MyBatis(国税)_Test

1.1、ORM介绍

对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),用于实现面向对象编程语言里不同类型系统的数据之间的转换。它是创建了一个可在编程语言里使用的“虚拟对象数据库”。简单来说ORM简化了应用程序对数据库的访问,实现了将数据库中的数据与程序中的对象进行相互映射,数据库中的一行记录可以对应一个对象,一个强类型的集合可以对应一张表。

MyBatis(国税)_Java_02

MyBatis(国税)_xml_03

1.2、常见的ORM框架与库

自己定义的JDBCUtil缺点:没有数据库连接池,影响性能;功能简单,不能应对复杂需求;没有缓存机制;
DBUtils:Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。如果自己想学习写框架,可以从该开源项目开始。

  1. Hibernate:全自动 需要些hql语句,与Struts、Spring组成SSH的搭配
  2. SSH(Struts2、Spring、Hibernate) S2SH
  3. Struts:MVC框架;Hibernate:ORM框架,冬眠;Spring:IOC、AOP…
  4. MyBatis:半自动 自己写sql语句,可操作性强,小巧,最开始iBatis
  5. JPA:(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。

 

MyBatis(国税)_MyBatis_04

1.3、MyBatis

MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github,网址:https://github.com/mybatis。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。
用xml文件构建SqlSessionFactory实例是非常简单的事情。推荐在这个配置中使用类路径资源(classpath resource),但你可以使用任何Reader实例,包括用文件路径或file://开头的url创建的实例。MyBatis有一个实用类----Resources,它有很多方法,可以方便地从类路径及其它位置加载资源。
优点:

  1. 1. 易于上手和掌握。
  2. 2. sql写在xml里,便于统一管理和优化。
  3. 3. 解除sql与程序代码的耦合。
  4. 4. 提供映射标签,支持对象与数据库的orm字段关系映射
  5. 5. 提供对象关系映射标签,支持对象关系组建维护
  6. 6. 提供xml标签,支持编写动态sql。

git地址:https://github.com/mybatis/

下载源码:https://github.com/mybatis/mybatis-3/releases

下载Jar包:https://github.com/mybatis/mybatis-3

官方文档:http://www.mybatis.org/mybatis-3/zh/index.html

MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

二、MyBatis示例

2.1、MyBatis基础

MyBatis(国税)_Test_05

结果:

MyBatis(国税)_xml_06

添加包

MyBatis(国税)_xml_07

mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<property name="username" value="tax"/>
<property name="password" value="orcl"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/tax/mapping/bookMapping.xml"/>
</mappers>
</configuration>

 

Book.java POJO对象

package com.tax.model;

/**图书实体 Bean POJO*/
public class Book {
/**编号*/
private int id;
/**书名*/
private String title;
/**类型*/
private String typename;
/**价格*/
private Double price;
/**状态*/
private String state;

@Override
public String toString() {
return "Book{" +
"id=" + id +
", title='" + title + '\'' +
", typename='" + typename + '\'' +
", price=" + price +
", state='" + state + '\'' +
'}';
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getTypename() {
return typename;
}

public void setTypename(String typename) {
this.typename = typename;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}
}

bookMaping.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.tax.mapping.bookMapper">
<!--
根据id查询得到一个book对象
-->
<select id="getBookById" resultType="com.tax.model.Book">
select id, title, typename, price, state from book where id=#{id}
</select>
<select id="getAllBooks" resultType="com.tax.model.Book">
select id, title, typename, price, state from book
</select>
</mapper>

BookDao 数据访问

package com.tax.dao;

import com.tax.model.Book;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**图书数据访问*/
public class BookDao {
/**获得图书通过编号*/
public Book getBookById(int id){
//将mybatis的配置文件转换成输入流,读配置文件
InputStream cfg=this.getClass().getClassLoader().getResourceAsStream("mybatis.xml");
//根据配置文件构建会话工厂
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(cfg);
//创建会话
SqlSession session=factory.openSession();
//调用方法getBookById带入参数1获得单个图书对象
Book book=session.selectOne("com.tax.mapping.bookMapper.getBookById",id);
//关闭会话
session.close();
return book;
}

public static void main(String[] args) {
BookDao dao=new BookDao();
//输出
System.out.println(dao.getBookById(3));
}
}

运行结果:

Book{id=3, title='Java并发编程的艺术', typename='软件工程', price=45.4, state='未借出'}

 2.2、JUnit单元测试

添加JUnit依赖

MyBatis(国税)_Java_08

添加测试的包与类

MyBatis(国税)_MyBatis_09

MyBatis(国税)_xml_10

package com.tax.test;

import com.tax.dao.BookDao;
import com.tax.model.Book;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Assert.*;

public class BookDaoTest {
@Test
public void getBookById(){
BookDao dao=new BookDao();
Book book=dao.getBookById(1);
System.out.println(book);
//断言,期待1,实际2
//Assert.assertEquals(1,2);
//不为空就通过
Assert.assertNotNull(book);
}

}

 

其它注解

import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

public class CalculatorTest {

private static Calculator calculator = new Calculator();

//每个方法测试前调用
@Before
public void clearCalculator() {
calculator.clear();
}

//每个方法测试完以后调用
@After
public void tearDown()
{
}

//@Test:测试方法,表明这是一个测试方法。在Junit中将会自动被执行。
@Test
public void add() {
calculator.add(1);
calculator.add(1);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 2);
}

@Test
public void subtract() {
calculator.add(10);
calculator.substract(2);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 8);
}

//给测试函数设定一个执行时间,超过了这个时间(400毫秒),它们就会被系统强行终止
@Test(timeout=400)
public void divide() {
calculator.add(8);
calculator.divide(2);
//第一个参数是预期的,第二个参数是真实的
assert calculator.getResult() == 5;
}

//使用注释来声明该异常是预期的,异常测试是Junit4中的最大改进
@Test(expected = ArithmeticException.class)
public void divideByZero() {
calculator.divide(0);
}
//@Ignore:忽略的测试方法,标注的含义就是“某些方法尚未完成,暂不参与此次测试”
@Ignore("not ready yet")
@Test
public void multiply() {
calculator.add(10);
calculator.multiply(10);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 100);
}
}

注解

@Test 测试方法,表明这是一个测试方法。在Junit中将会自动被执行。
@Test(timeOut=400) 给测试函数设定一个执行时间,超过了这个时间(400毫秒),它们就会被系统强行终止
@Test(expected = ArithmeticException.class) 使用注释来声明该异常是预期的,异常测试是Junit4中的最大改进
@Ignore("not ready yet") 忽略的测试方法,标注的含义就是“某些方法尚未完成,暂不参与此次测试”
@Before 每个方法测试前调用
@After 每个方法测试完以后调用
@BeforeClass 每个类运行前调用,并且只调用一次
@AfterClass 每个类运行后调用,并且只调用一次

2.3、XML+接口实现CRUD

BookDao接口

package com.tax.dao2;

import com.tax.model.Book;

import java.util.List;
public interface BookDao {
public Book getBookById(int id);

public List<Book> getAllBooks();

public int add(Book book);

public int update(Book book);

public int deleteById(int id);
}

 

MyBatis工具类

package com.tax.dao2;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public abstract class MyBatisUtil {

//GC不理static
private static SqlSessionFactory factory=null;
public static SqlSessionFactory getSqlSessionFactory(){
if(factory==null){
// 获得环境配置文件流
InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("mybatis.xml");
// 创建sql会话工厂
factory = new SqlSessionFactoryBuilder().build(config);
}
return factory;
}

//获得会话
public static SqlSession getSession(){
return getSqlSessionFactory().openSession(true);
}

/**
* 获得得sql会话
* @param isAutoCommit 是否自动提交,如果为false则需要sqlSession.commit();rollback();
* @return sql会话
*/
public static SqlSession getSession(boolean isAutoCommit){
return getSqlSessionFactory().openSession(isAutoCommit);
}

}

 

Book表映射文件

<?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.tax.dao2.BookDao">
<!--
根据id查询得到一个book对象
-->
<select id="getBookById" resultType="Book">
select id, title, typename, price, state from book where id=#{id}
</select>

<select id="getAllBooks" resultType="Book">
select id, title, typename, price, state from book
</select>

<insert id="add" parameterType="Book">
insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})
</insert>

<update id="update" parameterType="Book">
update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}
</update>

<delete id="deleteById">
delete from book where id=#{id}
</delete>
</mapper>

 

BookDaoImpl实现

package com.tax.dao2;

import com.tax.model.Book;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class BookDaoImpl implements BookDao {
@Override
public Book getBookById(int id) {
SqlSession session = null;
try {
session = MyBatisUtil.getSession();
BookDao dao = session.getMapper(BookDao.class);
return dao.getBookById(id);
} finally {
session.close();
}
}

@Override
public List<Book> getAllBooks() {
SqlSession session = null;
try {
session = MyBatisUtil.getSession();
BookDao dao = session.getMapper(BookDao.class);
return dao.getAllBooks();
} finally {
session.close();
}
}

@Override
public int add(Book book) {
SqlSession session = null;
try {
session = MyBatisUtil.getSession();
BookDao dao = session.getMapper(BookDao.class);
return dao.add(book);
} finally {
session.close();
}
}

@Override
public int update(Book book) {
SqlSession session = null;
try {
session = MyBatisUtil.getSession();
BookDao dao = session.getMapper(BookDao.class);
return dao.update(book);
} finally {
session.close();
}
}

@Override
public int deleteById(int id) {
SqlSession session = null;
try {
session = MyBatisUtil.getSession();
BookDao dao = session.getMapper(BookDao.class);
return dao.deleteById(id);
} finally {
session.close();
}
}
}

 

测试文件

package test.com.tax.dao2;

import com.tax.dao2.BookDao;
import com.tax.dao2.BookDaoImpl;
import com.tax.model.Book;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;

/**
* BookDaoImpl Tester.
*
* @author <Authors name>
* @version 1.0
* @since <pre>03/15/2018</pre>
*/
public class BookDaoImplTest {

BookDao dao;

@Before
public void before() throws Exception {
dao = new BookDaoImpl();
}

@After
public void after() throws Exception {
}

/**
* Method: getBookById(int id)
*/
@Test
public void testGetBookById() throws Exception {
System.out.println(dao.getBookById(3));
}

/**
* Method: getAllBooks()
*/
@Test
public void testGetAllBooks() throws Exception {
for (Book book:dao.getAllBooks()) {
System.out.println(book);
}
}

/**
* Method: add(Book book)
*/
@Test
public void testAdd() throws Exception {
Book book=new Book();
book.setTypename("计算机");
book.setState("未借出");
book.setTitle("Spring 入门到放弃");
book.setPrice(23.5);
Assert.assertEquals(1,dao.add(book));
}

/**
* Method: update(Book book)
*/
@Test
public void testUpdate() throws Exception {
Book book=dao.getBookById(49);
book.setTypename("从入门到精通");
Assert.assertEquals(1,dao.update(book));
}

/**
* Method: deleteById(int id)
*/
@Test
public void testDeleteById() throws Exception {
Assert.assertEquals(1,dao.deleteById(49));
}


}

 

结果:

MyBatis(国税)_Test_11

 2.4、基于注解实现CRUD

MyBatis(国税)_xml_12

使用注解不再需要mapping文件

BookDao接口如下:

package com.tax.dao;

import com.tax.model.Book;
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 java.util.List;
public interface BookDao {
@Select("select id, title, typename, price, state from book where id=#{id}")
public Book getBookById(int id);

@Select("select * from book")
public List<Book> getAllBooks();

@Insert("insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})")
public int add(Book book);

@Update("update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}")
public int update(Book book);

@Delete("delete from book where id=#{id}")
public int deleteById(int id);
}

mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<property name="username" value="tax"/>
<property name="password" value="orcl"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="com.tax.dao.BookDao"/>
</mappers>
</configuration>

其它内容与2.3节一样。

2.5、别名与数据源

bookMapping.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.tax.dao2.BookDao">
<!--
根据id查询得到一个book对象
-->
<select id="getBookById" resultType="B">
select id, title, typename, price, state from book where id=#{id}
</select>

<select id="getAllBooks" resultType="B">
select id, title, typename, price, state from book
</select>

<insert id="add" parameterType="Book">
insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})
</insert>

<update id="update" parameterType="Book">
update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}
</update>

<delete id="deleteById">
delete from book where id=#{id}
</delete>
</mapper>

mybatis.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 type="com.tax.model.Book" alias="B"></typeAlias>
<package name="com.tax.model"></package>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<property name="username" value="tax"/>
<property name="password" value="orcl"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/tax/mapping/bookMapping.xml"/>
</mappers>
</configuration>

数据源

db.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
username=tax
password=orcl

mybatis.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>
<properties resource="db.properties"></properties>
<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 class="com.tax.dao.BookDao"/>
</mappers>
</configuration>

 2.6、Java Web中整合MyBatis(展示与删除功能)

项目结构:

MyBatis(国税)_xml_13

BookServlet

package com.tax.action;

import com.tax.dao.BookDao;
import com.tax.dao.BookDaoImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");

//获得action类型
String act=request.getParameter("act");
//如果当前的动作是删除
if(act.equals("delete"))
{
//获得URL中要删除的图书编号
int id=Integer.parseInt(request.getParameter("id"));
BookDao dao=new BookDaoImpl();
if(dao.deleteById(id)>0){ //执行删除并成功
request.setAttribute("msg","删除成功!");
}else{
request.setAttribute("msg","删除失败!");
}
//转发到index.jsp页面
request.getRequestDispatcher("index.jsp").forward(request,response);
}else if(act.equals("edit")){

}else{
response.sendRedirect("index.jsp");
}
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}

 

index.jsp

<%@ page import="com.tax.dao.BookDao" %>
<%@ page import="com.tax.dao.BookDaoImpl" %>
<%@ page import="com.tax.model.Book" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
BookDao dao = new BookDaoImpl();
List<Book> books = dao.getAllBooks();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>图书列表</title>
<style>
body{
font-size:14px;
}
#tabBooks {
width: 80%;
}

#tabBooks, #tabBooks td {
border-collapse: collapse;
}
.red{
color:red;
}
.green{
color:green;
}
</style>
</head>
<body>
<h2>图书列表</h2>
<table border="1" id="tabBooks">
<tr>
<td>
<input type="checkbox" id="chbAll"/>
</td>
<td>序号</td>
<td>书名</td>
<td>价格</td>
<td>类型</td>
<td>状态</td>
<td>操作</td>
</tr>
<%for (int i = 0; i < books.size(); i++) {%>
<tr>
<td>
<input type="checkbox" name="id" value=""/>
</td>
<td>
<%=i + 1%>
</td>
<td><%=books.get(i).getTitle()%>
</td>
<td><%=books.get(i).getPrice()%>
</td>
<td><%=books.get(i).getTypename()%>
</td>
<td class="<%=books.get(i).getState().equals("未借出")?"green":"red"%>">
<%=books.get(i).getState()%>
</td>
<td>
<a href="BookServlet?act=delete&id=<%=books.get(i).getId()%>" class="delete" onclick="return isDel()">删除</a>
</td>
</tr>
<%}%>
</table>
<script>
// var items=document.querySelectorAll(".delete");
// for(var i=0;i<items.length;i++){
// items[i].onclick=function () {
// return confirm("您确定要删除吗?");
// }
// }

function isDel() {
return confirm('您确定要删除吗?');
}
</script>
</body>
</html>

 结果:

MyBatis(国税)_MyBatis_14

 2.7、参考代码

​https://git.coding.net/zhangguo5/WebReadMyBatis.git​

三、MyBatis总结

使用jdbc开发时,和mybatis相比的不足 
1,数据库连接,使用时就创建,不使用就释放,对数据库进行频繁连接开关和关闭,造成数据库资源浪费,影响数据库的性能 
解决:使用数据库连接池管理数据库的连接 
2,sql语句使用硬编码在java程序中,修改sql语句,就需要重新编译java代码,不利于系统维护 
解决:把sql语句放在xml配置文件中,修改sql语句也不需要重新编译java代码 
3,向预编译语句PreparedStatement中设置参数,对占位符位置和设置参数值,硬编码,修改sql语句也不需要重新编译java代码 
解决:把sql语句和占位符设置参数值放在xml配置文件中 
4,从result中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码 
解决:将查询的结果集,自动映射成 java对象

二 mybatis框架,是一个持久层框架,是apache下的顶级项目 

mybatis让程序员将主要精力放在sql上,通过mytabis提供的映射方式,自动生成满足需要的sql语句 

mybatis可以向PreparedStatement中输入参数自动进行输入映射,将查询结果集灵活的映射成Java对象(输出映射),输入映射和输出映射这是mybatis的核心 

mybatis框架执行流程图 

MyBatis(国税)_MyBatis_15


三 mybatis的工作环境搭建和架构示意图 

MyBatis(国税)_xml_16

 

四 mybatis的开发 

1.映射文件的开发如下图 

MyBatis(国税)_MyBatis_17


2,映射文件配置好了之后,还需要在全局配置文件sqlMapConfig.xml中添加映射文件 

MyBatis(国税)_Java_18

 

3,sqlsession会话去执行操作查询数据库映射文件,下图中的错误纠正为’%${value}%’ 

MyBatis(国税)_xml_19


查询出的是单条记录使用selectOne,下图中的错误纠正为把“1”改为int类型的1 

sqlsession.selectOne(“test.findUserById”, 1); 

MyBatis(国税)_MyBatis_20

 

查询出的是多条记录使用selectList 

sqlsession.selectList(“test.findUserByName”, “hello”); 

MyBatis(国税)_Test_21

 

4,添加用户映射文件配置如下: 

MyBatis(国税)_xml_22


程序代码: 

MyBatis(国税)_Test_23


5,总结: 

MyBatis(国税)_Java_24

 

四 mybatis开发dao方法 

mybatis的配置文件不变 

1,先使用原型的开发dao方法 

开发接口 

MyBatis(国税)_MyBatis_25

 

2, 开发接口实现 

MyBatis(国税)_xml_26


3, 测试代码 

MyBatis(国税)_Test_27


4,总结 

MyBatis(国税)_Test_28

 

五 mybatis利用mapper代理开发dao(重点掌握) 

mapper代理开发,就不需要接口的实现类,只需要接口UserMapper.java和映射文件UserMapper.xml就可以了,但是遵循一定的开发规范: 

1,在UserMapper.xml文件中namespace等于UserMapper接口地址 

MyBatis(国税)_Test_29

 

2,UserMapper.java接口中的方法名要和UserMapper.xml中的statement的id一致 

3,UserMapper.java接口中的方法输入参数要和UserMapper.xml中的statement的parameterType指定的类型一致 

4,UserMapper.java接口中的方法的返回值类型要和UserMapper.xml中的statement的resultType指定的类型一致 

测试代码: 

MyBatis(国税)_Test_30

 

上图画线区域:这里没有实现接口的实现类,而是使用mybatis生成的代理对象来生成UserMappper接口的对象,从而能够调用其方法

mapper代理开发dao出现的问题总结: 
1,代理对象内部调用selectOne或selectList 
如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库,也可以使用selectList查询。 
如果mapper方法返回集合对象,代理对象内部通过selectList查询 数据库,不能使用selectOne查询,否则会出错。 
问题是: 编译期间不会报错,二者容易写错使用。 
2,mapper接口方法参数只有一个 
根据规范编写的代理对象的传入参数只能有一个(mapper.xml文件中的parameterType参数只有一个),不利于系统的扩展 
解决:即使mapper接口中只有一个参数,可以使用包装类型的pojo满足不同的业务方法需求

mybatis的一些细节剖析:

1,全局配置文件sqlMapConfig.xml中配置内容如下:

  1. properties(属性) 
    注意:mybatis将按照下面的顺序来加载属性: 
    (1)在properties元素体内定义的属性首先被读取。(可以在此属性中加入jdbc的配置文件db.properties),在sqlMapConfig.xml中就不需要对数据库连接参数进行硬编码了。 
  2. settings全局参数设置 
    mybatis框架运行时可以调整一些运行参数,会影响mybatis运行行为,所以建议不要随便修改 
    比如:二级缓存,开启延时加载。。。
  3. typeAliases(别名) 重点掌握 
<typeAliases>
<!--针对单个别名定义
type:类型的路径
alias:别名 -->
<typeAlias type="com.jary.mybatis.po.User" alias="user" />
<!--还可以进行批量别名定义
指定包名,mybatis自动扫描包中的po类 -->
<package name="com.jary.mybatis.po" />
</typeAliases>

上面的别名定义后,在mapper.xml中就可以这样使用了 

user代替了输出结果类型com.jary.mybatis.po.User。

4.映射文件(mapper)

通过resource加载单个的映射文件

<mapper resource="mapper/UserMapper.xml" />
  • 1

通过mapper接口加载单个mapper,要遵循一定的规范: 

(1)前提是使用mapper代理开发(已经有4个规范) 

(2)需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在同一目录下 

MyBatis(国税)_Test_31

<mapper class="com.jary.mybatis.mapper.UserMapper" />
  • 1

通过批量加载mapper(推荐使用):实现条件是 

要满足mapper接口加载映射文件和使用mapper代理开发同时满足 

MyBatis(国税)_MyBatis_32

 

mybatis的一些细节剖析结束

mybatis的核心输入映射和输出映射开始:

输入映射 

通过parameterType指定输入参数类型,类型可以是简单类型、hashmap、pojo的包装类型 

1,传递pojo的包装对象 

(1)需求 

完成用户信息的综合查询,需要传入查询条件复杂(可能包括用户信息,商品信息,商品订单等),这样靠一个parameterType只能传入一个输入参数,所有需要pojo的包装类型来实现 

(2)定义包装类型pojo 

针对上面的需求,在包装类型的pojo中把这些复杂的查询条件包装进去,定义包装类UserQueryVo,把需要查询的条件全部定义在里面 

MyBatis(国税)_xml_33

 

上图中标注的用户查询条件使用的是User的扩展类(因为User类一般是由逆向工程自动生成的,不要进行修改,所有使用的扩展类来实现) 

映射文件UserMapper.xml配置 

MyBatis(国税)_MyBatis_34

 

UserMapper.java接口文件的配置 

MyBatis(国税)_Java_35

 

上图中,把包装类作为参数传入,返回值是一个用户列表所以用list集合接收测试代码如下图: 

MyBatis(国税)_MyBatis_36

输出映射 

1,resultType 

使用resultType进行输出映射时,只有查询输出结果列名和pojo中的属性名一致才可以,映射成功 

如果查询出来的列名和pojo中的属性名没有一个一致的,就不会创建pojo对象 

如果查询出来的列名和pojo中的属性名有一个一致,就会创建pojo对象 

输出pojo对象和pojo列表 

不管是输出的pojo单个对象还是一个列表(list中包含pojo),在mapper.xml中resultType指定的类型是一样的 

在mapper.java指定的方法返回值类型不一样: 

(1)输出单个pojo对象,方法返回值是个单个对象类型 

(2)输出pojo对象list,方法返回值就是list对象类型 

在动态代理对象中,是根据mapper方法的返回值类型来确定是调用selectOne(返回单个对象)还是selectList(返回集合对象) 

2,resultMap 

使用resultMap进行映射时,查询结果列名和pojo的属性名不一致时,resultMap会对列名和pojo属性名进行映射,保证其成功映射 

使用resultMap需要这二步: 

(1)定义resultMap 

MyBatis(国税)_MyBatis_37

 

(2)使用resultMap作为statement的输出映射类型 

MyBatis(国税)_Java_38

 

mybatis的核心输入映射和输出映射结束:

mybatis的动态sql和sql片段开始:

动态sql 

mybatis核心就是对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接和组装。 

需求:用户信息查询的综合信息需要使用动态sql 

对查询条件进行判断,如果出入参数不为空,才进行拼接 

MyBatis(国税)_Java_39

 

测试代码需要注意的是如下图: 

MyBatis(国税)_Java_40

 

如果不设置某个值,条件将不拼接在sql中sql片段 

需求:将上面的动态sql(重复的sql语句)抽取出来做成一个片段,方便其他statement语句重复使用sql片段 

MyBatis(国税)_MyBatis_41

 

使用sql片段 

MyBatis(国税)_MyBatis_42

使用foreach标签遍历 

给sql传入数组或者集合时,mybatis使用foreach解析 

需求:在用户信息的综合查询中增加多个id传入 

sql语句如下: 

select * from user where id=1 or id=3 or id=5 

也可以使用select * from user where id in(1,3,5) 

MyBatis(国税)_Java_43

 

mybatis的动态sql和sql片段结束mybatis高级映射开始: 

一、 高级映射一对一查询(使用到assocition标签实现关联对象的一对一查询映射),分别使用resultType和resultMap,并且比较二者的区别 

MyBatis(国税)_xml_44

 

还有一点就是,resultType查询关联列表结果列如果和pojo属性名不一致,需要自己创建扩展类(继承包括结果集列名多的pojo对象,这样可以少写一点属性名)。resultMap则不需要创建扩展类,而是把关联信息的对象注入,从而实现结果集列名和pojo属性名保持一致。 

二、高级映射一对多查询(使用collection标签来实现关联对象的一对多查询映射),一对多,就是关联的对象查询结果是一个List集合 

开发步骤: 

(1)首先写sql语句 

需求:查询订单及订单明细信息(一个订单包含多个订单明细,所以一对多) 

主表:订单表 

关联表:订单明细表 

经过之前一对一查询(用户的订单)的分析,我们只需要在此基础上关联订单明细表即可。 

MyBatis(国税)_Test_45

 

(2)pojo类(resultType时用到扩展类,这里我们使用resultMap不需要包装类) 

MyBatis(国税)_xml_46

 

(3)mapper.xml(这里我们使用了resultMap的继承,不需要重新关联订单表和用户表,通过继承之前的一对一(用户查询订单)所写的二个表,可以减少大量的重复代码。同时使用了collection集合标签将关联查询出的多条记录映射到List集合中) 

MyBatis(国税)_Java_47


(4)mapper.java 

MyBatis(国税)_Test_48

一对多查询总结: 
mybatis使用resultMap的collection(resultType没有此标签)对关联查询的多条记录映射到一个list集合中。 
使用resultType通过双重循环遍历可以实现,去除重复记录,将订单明细映射在orderdetail中(了解) 
多对多查询实例和上边类似。主要是搞清楚各个表之间的对应关系,订单的collection中嵌套订单明细的collection,而订单明细的collection中嵌套商品信息。

mybatis高级映射结束

mybatis的延迟加载和缓存技术开始 

mybatis一级缓存 

MyBatis(国税)_Test_49

 

mybatis的二级缓存mybatis默认是没有开启二级缓存的。 

开启二级缓存需要在mybatis的全局配置文件sqlMapConfig.xml中加入 


除了开启二级缓存开关外,还需要在各自的mapper.xml中开启二级缓存。 

MyBatis(国税)_xml_50

原理图: 

MyBatis(国税)_MyBatis_51

 

如上图:sqlsession1去查询id为1的用户信息,查询到用户信息就会查询数据存放在二级缓存区域(hashmap)中 

sqlsession2去查询id为1的用户信息,首先去缓存中查找是否存在数据,如果存在就直接从二级缓存中取出数据。 

二级缓存和一级缓存的区别:二级缓存的范围更大,多个sqlsession 

可以共享usermapper的二级缓存。 

二级缓存是根据mapper的namespace来划分的,相同namaspace下的mapper共享二级缓存,反之 

如果sqlsession3去执行相同mapper下sql,并执行commit()操作,则清空该命名空间下的二级缓存

二级缓存的测试代码:

MyBatis(国税)_Test_52

上面涂黄部分要特别注意,sqlsession关闭时才可以把数据写到二级缓存区域中,如果本namespace下的sqlsession执行了commit()操作,二级缓存就会清空

禁用二级缓存 

也可以禁用单个查询的二级缓存,这样要保证每次查询的都是最新数据。 

MyBatis(国税)_Test_53

刷新二级缓存(就是清空缓存,切记) 

MyBatis(国税)_Java_54

 

总结:一般情况下,执行commit()操作之后,都要刷新缓存,因此flushCache都设为true,来避免数据的脏读。

mybatis cache的参数设置 
flushInterval(刷新间隔),可以为任意整数,单位为毫秒值,这个比较有用。

mybatis和第三方分布式缓存框架整合(ehcache,redis,memcache) 

mybatis在缓存方面还是比较弱,特别是分布式缓存不支持 

MyBatis(国税)_Test_55

 

我们的系统为了提高系统并发,性能,一般对系统进行分布式部署(集群部署方式)整合方法 

mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口即可 

mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。 

MyBatis(国税)_xml_56

二级缓存的应用场景(实际开发中用 刷新间隔) 

MyBatis(国税)_xml_57

二级缓存额局限性 

MyBatis(国税)_MyBatis_58

 

细粒度缓存,就是修改一个商品信息(即执行commit()方法),只修改缓存中这一个商品的信息,其余的信息不清空。

mybatis的延迟加载和缓存技术结束

mybatis和spring的整合(重点掌握)开始

1、整合的思路: 

(1)首先需要spring通过单例方式管理sqlSessionFactory 

(2)spring和mybatis整合生成代理对象,使用SqlSessionFactory创建sqlSession会话(此步是由spring和mybatis整合自动完成) 

(3)持久层的mapper,dao都需要由spring来管理 

2、环境的搭建 

MyBatis(国税)_MyBatis_59

 

上面的sqlmap目录下的User.xml是为了原始dao开发使用的。还要加载spring,mybatis,mybatis-srping等jar包。 

3、在spring的配置文件中配置sqlSessionFactory和数据源 

sqlSessionFactory在mybatis和spring的整合包下 

MyBatis(国税)_MyBatis_60

 

上图中:使用C3P0配置数据库连接池,属性参数名要按照规定写,不能自己定义,否则会报错,而使用dbcp就可以自定义参数名,这点注意。 

在加载配置文件时,都要加上类路径名classpath 

在使用原始dao开发时,属性name值要与UserDaoImpl类中变量名一致(特别是大小写) 

4、*原始Dao的开发(和spring整合后)* 

4.1 User.xml(也称mapper.xml更准确) 

MyBatis(国税)_xml_61

 

和spring整合后,需要使用spring来管理mapper,spring配置文件为applicationContext.xml 

还有mybatis的配置文件来加载User.xml 

MyBatis(国税)_MyBatis_62

 

4.2 UserDAO 

MyBatis(国税)_Java_63

 

基本上不用改变 

4.3 UserDaoImpl(重点在Dao的实现类上) 

MyBatis(国税)_Java_64


上图中的代码最重要的就是继承了SqlSessionDaoSupport通过this.getSqlSession()来得到SqlSession会话 

这里也不需要写sqlSession的事务提交(更新操作不用写)和sqlSession关闭 

4.4 测试代码 

MyBatis(国税)_xml_65

5、使用mapper代理来开发 (mybatis和spring整合后) 
和利用原始dao开发差不多,只是不需要dao接口的实现类 
而是根据一个规范来实现dao接口生成代理对象

5.1规范: 

(1)mapper.xml中的namespace命名空间等于mapper.java的全路径名 

MyBatis(国税)_xml_66


(2)mapper.xml和mapper.java应在同一个目录下 

MyBatis(国税)_MyBatis_67

 

(3)mapper.xml中的statement语句的输入参数paramType类型应与mapper.java中方法中传递的参数类型一致 

MyBatis(国税)_MyBatis_68

 

MyBatis(国税)_Test_69


(4)mapper.xml中的statement语句的输出参数resultType类型应与mapper.java中方法返回值类型一致 

MyBatis(国税)_Test_70

 

MyBatis(国税)_Java_71


5.2 让spring来管理mapper,在配置文件中 

MyBatis(国税)_xml_72

 

重点在这里,使用mybatis和spring的整合包中MapperFactoryBean来实现mapper接口生成代理对象 

属性值有mapperInterface和sqlSessionFactory 

总结:此方法存在一个大问题,需要针对每个mapper进行配置,太麻烦 

终极解决方案: 通过mapper批量扫描,从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册 

MyBatis(国税)_Java_73

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
  • 1

上面代码,不能使用ref而是使用value,刚开始用错了。 

开发中推荐使用自动扫描, 

mybatis和spring的整合(重点掌握)结束 

mybatis的逆向工程(了解会用就行) 

MyBatis(国税)_Test_74


generator.xml的配置,这里要记住,上图中最下边table后面的一长串值等于false的属性,是为了不生成其他与我们无关的example等代码 

下面需要mybatis-generator-core-1.3.2.jar和generator.xml文件在同于目录下,并且建立src目录接收生成的文件 

MyBatis(国税)_MyBatis_75


生成后的如下图 

MyBatis(国税)_xml_76

 

没有了example的无用类了,比较干净,推荐使用

1.接口绑定:两种方法,基于注解或者基于xml文档mapper,但要注意mapper的namespace要与接口路径完全一致。

2.orm格式转换:通过设置resultMap和ResultType,将数据库中的记录转换为代码的bean对象。得到list或者对象。

3.通过parameterType接收参数,进行动态sql生成。运用ognl表达式

4.走缓存,设置二级缓存。设置二级缓存源。

5.为什么要通过orm框架来走缓存呢?因为自己配置缓存策略相对复杂,比如当insert/update/delete时,要清除相应的缓存。当某些情况select又要添加进缓存。

6.orm框架,orm框架,它是怎么进行对象和数据库中表的转换的呢?答:数据库中的表要与代码中的类一一对应,包括属性。这样不就能进行匹配转换了嘛。

5.返回list,必须要配置resultMAp

6.insert操作时,要注意主键 主键生成策略,要设置useGeneraterKey = true,和 keyProperty="id",指定哪个是主键

<insert id="addUser" parameterType="User" 
useGeneratedKeys="true" keyProperty="id">
insert into user(userName,userAge,userAddress)
values(#{userName},#{userAge},#{userAddress})
</insert>

7.spring在于mybatis集成时,spring负责什么呢?谁来维护datasource,谁来建立sqlSessionFactory?

答:spring作为多个框架的粘合剂,spring负责建立datasource,sqlsessionFactpry。充分利用spring的ioc和aop功能。

spring 配置文件:applicationContext.xml 


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">//spring管理配置datasource
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> //spring管理配置sqlsessionFactory
<!--dataSource属性指定要用到的连接池-->
<property name="dataSource" ref="dataSource"/>
<!--configLocation属性指定mybatis的核心配置文件-->
<property name="configLocation" value="config/Configuration.xml"/>
</bean>


8.Mybatis的dao实现接口(接口绑定),是由mybatis来实现的,那又怎么来使用这个实现类呢?

答:当然是注册到spring里了,作为一个bean使用。

即:mybatis的dao实现类,也都要注册到spring的ioc容器中,以便利用spring的ioc和aop功能。

注意此时dao实现类,的具体类是mybatis固定的org.mybatis.spring.mapper.MapperFactoryBean类,这个类专门用来生成具体的dao实现类。

但要记住,一切的增删改查都是通过session来进行的,所以dao实现类要di依赖注入sqlSessionFactory这个属性。

再利用mapperInterface指定具体的mapper接口类。

spring 配置文件:applicationContext.xml
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
<!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象-->
<property name="mapperInterface" value="com.yihaomen.mybatis.inter.IUserOperation" />
</bean>


9.即:mybatis的dao实现类,也都要注册到spring的ioc容器中,以便利用spring的ioc和aop功能。

10.spring的配置文件applicationContext.XML负责配置与数据库相关,与mybatis sqlSessionFaction 整合,扫描所有mybatis mapper 文件等相关内容。

事务管理器也在spring的配置文件中配置,同时要依赖注入datasource属性

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

11.mybatis的分页功能,可以自己利用mysql代码实现,也可以利用mybatis分页插件,如pageHelper

12.mybatis的传入参数只能是一个,只能有1个。可以是各种​​Java​​的基本数据类型:包含int,String,Date等。基本数据类型作为传参,只能传入一个。通过#{参数名} 即可获取传入的值 ,复杂数据类型:包含JAVA实体类、Map。通过#{属性名}或#{map的KeyName}即可获取传入的值,但是如果想传入一个collection怎么办呢?

经查找后发现可以使用mapper配置文件中的foreach语句,借用别人写的文章:

13. foreach

对于动态SQL 非常必须的,主是要迭代一个集合,通常是用于IN 条件。List 实例将使用“list”做为键,数组实例以“array” 做为键。

foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。

14. 在​​Java​​实体对象对中,一对多可以根据List和Set来实现,两者在mybitis中都是通过collection标签来配合使用

 

15.

一对一关联

根据班级id查询班级信息(带老师的信息)
10 ##1. 联表查询
11 SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;


<select id="getClass" parameterType="int" resultMap="ClassResultMap">
24 select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
25 </select>
26 <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
27 <resultMap type="me.gacl.domain.Classes" id="ClassResultMap">
28 <id property="id" column="c_id"/>
29 <result property="name" column="c_name"/>
30 <association property="teacher" javaType="me.gacl.domain.Teacher">
31 <id property="id" column="t_id"/>
32 <result property="name" column="t_name"/>
33 </association>
34 </resultMap>


<!-- 
37 方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
38 SELECT * FROM class WHERE c_id=1;
39 SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
40 -->
41 <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
42 select * from class where c_id=#{id}
43 </select>
44 <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
45 <resultMap type="me.gacl.domain.Classes" id="ClassResultMap2">
46 <id property="id" column="c_id"/>
47 <result property="name" column="c_name"/>
48 <association property="teacher" column="teacher_id" select="getTeacher"/>
49 </resultMap>
50
51 <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
52 SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
53 </select>

 MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:

  • property:对象属性的名称
  • javaType:对象属性的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

一对一关联

根据班级id查询班级信息(带老师的信息)
10 ##1. 联表查询
11 SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;


<select id="getClass" parameterType="int" resultMap="ClassResultMap">
24 select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
25 </select>
26 <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
27 <resultMap type="me.gacl.domain.Classes" id="ClassResultMap">
28 <id property="id" column="c_id"/>
29 <result property="name" column="c_name"/>
30 <association property="teacher" javaType="me.gacl.domain.Teacher">
31 <id property="id" column="t_id"/>
32 <result property="name" column="t_name"/>
33 </association>
34 </resultMap>


<!-- 
37 方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
38 SELECT * FROM class WHERE c_id=1;
39 SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
40 -->
41 <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
42 select * from class where c_id=#{id}
43 </select>
44 <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
45 <resultMap type="me.gacl.domain.Classes" id="ClassResultMap2">
46 <id property="id" column="c_id"/>
47 <result property="name" column="c_name"/>
48 <association property="teacher" column="teacher_id" select="getTeacher"/>
49 </resultMap>
50
51 <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
52 SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
53 </select>

 MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:

  • property:对象属性的名称
  • javaType:对象属性的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

15.

2.6、MyBatis一对多关联查询总结

  MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。


16.mybatis调用存储过程

三、编辑userMapper.xml

  编辑userMapper.xml文件,添加如下的配置项

复制代码
1 <!--
2 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性
3 -->
4 <select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
5 CALL mybatis.ges_user_count(?,?)
6 </select>
7
8 <!--
9 parameterMap.put("sexid", 0);
10 parameterMap.put("usercount", -1);
11 -->
12 <parameterMap type="java.util.Map" id="getUserCountMap">
13 <parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
14 <parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
15 </parameterMap>
复制代码
四、编写单元测试代码

复制代码
1 package me.gacl.test;
2
3 import java.util.HashMap;
4 import java.util.List;
5 import java.util.Map;
6
7 import me.gacl.custom.model.ConditionUser;
8 import me.gacl.domain.User;
9 import me.gacl.util.MyBatisUtil;
10 import org.apache.ibatis.session.SqlSession;
11 import org.junit.Test;
12
13 /**
14 * @author gacl
15 * 测试调用存储过程
16 */
17 public class Test6 {
18
19 @Test
20 public void testGetUserCount(){
21 SqlSession sqlSession = MyBatisUtil.getSqlSession();
22 /**
23 * 映射sql的标识字符串,
24 * me.gacl.mapping.userMapper是userMapper.xml文件中mapper标签的namespace属性的值,
25 * getUserCount是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
26 */
27 String statement = "me.gacl.mapping.userMapper.getUserCount";//映射sql的标识字符串
28 Map<String, Integer> parameterMap = new HashMap<String, Integer>();
29 parameterMap.put("sexid", 1);
30 parameterMap.put("usercount", -1);
31 sqlSession.selectOne(statement, parameterMap);
32 Integer result = parameterMap.get("usercount");
33 System.out.println(result);
34 sqlSession.close();
35 }
36 }
复制代码

标签:mapper,public,mybatis,book,MyBatis,import,国税,id
From: https://blog.51cto.com/u_15674872/6004554

相关文章

  • mybatis 一级、二级缓存机制
     MyBatis提供了对缓存的支持,分为一级缓存和二级缓存  一级缓存是SqlSession级别的缓存。在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(HashMap......
  • SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel
    SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel 一、前言今天小编带大家一起整合一下easyExcel,之所以用这个,是因为easyExcel性能比较好,不会......
  • MyBatisPlus
    MyBatisPlus导入坐标SpringBoot并没有收录mybatisplus,所以需要自己导入坐标<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus......
  • 01-mybatis解析XML文件
    <?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><c......
  • mybatis踩坑之integer类型是0的时候会被认为0!=''是假
    当你的参数类型是integer类型,并且传的是0的时候,在SQL里面做if判断的时候<iftest="auditStatus!=nullandauditStatus!=''">ANDaudit_status=#{aud......
  • 数据源、JDBC、MyBatis、连接池(Druid)
    概念数据源(DataSource)是一种数据库对编程提供的一个接口,每个数据源对应一个数据库。一个例子就是在使用IDEA的数据库插件时,通常需要选择数据源,此处的数据源就是指这个......
  • 学习笔记——MyBatis自动映射与自定义映射;Mybatis延迟加载
    2023-01-10 一、MyBatis自动映射与自定义映射1、自动映射:在映射文件中使用的是“resultType”。指的是自动将数据库中表的字段与类中的属性进行关联映射。2、自定义映......
  • SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel
    一、前言今天小编带大家一起整合一下easyExcel,之所以用这个,是因为easyExcel性能比较好,不会报OOM!市面上常见的导入导出Excel分为三种:hutooleasyExcelpoihutool和eas......
  • Mybatis——实现批量更新
    一、概述mybatis中实现批量插入是很简单的,相比大家都知道,这里就不赘述,本文主要讲述如何实现批量更新。 下面介绍本文要讲的几种方式主要是在xml中实现,不包含需要改动代......
  • Mybatis
    缓存与Executor一级缓存一级缓存是sqlSession级别的,默认开启,在BaseExecutor中实现,其具体实现为key-value结构的HashMap。一级缓存命中条件1、查询sql和参数值必须相同;......