MyBatis1

MyBatis 简介

概念:Mybatis 开源免费框架.原名叫iBatis,2010在googlecode,2013年迁移到github
作用: 数据访问层框架。底层是对 JDBC 的封装.
优点:使用mybatis时不需要编写实现类,只需要写需要执行的sql命令。

环境搭建

1.导入jar包

2. 在 src 下新建全局配置文件(编写 JDBC 四个变量)
  1)没有名称和地址要求
  2)在全局配置文件中引入 DTD 或 schema
  3)全局配置文件内容
    <transactionManager/>中 type 属性可取值
      JDBC 事务管理使用 JDBC 原生事务管理方式
      MANAGED 把事务管理转交给其他容器.原生 JDBC 事务相当于setAutoMapping(false);(不自动提交)
    <dataSouce/>中 type 属性
      POOLED 使用数据库连接池
      UNPOOLED 不使用数据库连接池,和直接使用 JDBC 一样
      JNDI:java 命名目录接口技术

<?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>
    <!-- default引用environment的id,当前所使用的环境 -->
    <environments default="default">
        <!-- 声明可以使用的环境 -->
        <environment id="default">
            <!-- 使用原生JDBC事务 -->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="smallming"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/su/mapper/FlowerMapper.xml"/>
    </mappers>
</configuration>

3. 新建以 mapper 结尾的包,在包下新建:实体类名+Mapper.xml
  1)文件作用:编写需要执行的 SQL 命令
  2)把 xml 文件理解成实现类
  3)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">
<!-- namesapce:理解成实现类的全路径(包名+类名) -->
<mapper namespace="a.b" >
    <!-- id:方法名 
        parameterType:定义参数类型
        resultType:返回值类型.
        
        如果方法返回值是list,在resultType中写List的泛型,因为mybatis
        对jdbc封装,一行一行读取数据
    -->
    <select id="selAll" resultType="com.su.pojo.Flower">
        select * from flower
    </select>
</mapper>

4. 测试结果(只有在单独使用mybatis时使用,最后ssm整合时下面代码不需要编写.)

  1)service中:

/**
 * 在数据访问层处理异常和在控制器中处理异常,service中只抛出异常.
 * @author Administrator
 *
 */
public class FlowerServiceImpl implements FlowerService {

    @Override
    public List<Flower> show() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis.xml");
        //前面是'工厂设计模式'。实例化工厂对象时使用的是'构建者设计模式',名称标志:后面有Builder
        //构建者设计模式意义: 简化对象实例化过程
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //生产 SqlSession
        SqlSession session = factory.openSession();
        List<Flower> list = session.selectList("a.b.selAll");
        session.close();
        return list;
    }
}

  2)servlet中:

//大部分注解都有默认属性,如果注解中只给默认属性复制,可以省略属性名
//否则在注解的(属性名=属性值)格式
//如果一个属性是数组类型格式: 属性名={值,值} ,如果该数组只有一个值,可以省略大括号
//如果类型不是基本数据类型或String而是一个类类型,语法: 属性名=@类型
//注解中@表示引用注解声明
@WebServlet("/abc/b/show")
//@WebServlet(value={"/show"})
public class ShowServlet extends HttpServlet{ private FlowerService flowerService = new FlowerServiceImpl(); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<Flower> list = flowerService.show(); req.setAttribute("list", list); //相对路径 //只要路径中以/开头的都叫做全路径. 从项目根目录(WebContent)出发找到其他资源的过程 //只要不以/开头都是相对路径,相对路径是从当前资源出发找到其他资源的过程 //如果是请求转发 / 表示WebContent目录 //如果是重定向,静态资源引用,必须<img src=""/> <a href=""> <script src=""/> css引用时 其中 /都表示的是tomcat的webapps文件夹根目录 //服务器根目录 req.getRequestDispatcher("/index.jsp").forward(req, resp); } }

数据库连接池

1.在内存中开辟一块空间,存放多个数据库连接对象。
2.JDBCTomcatPool,直接由 tomcat 产生数据库连接池。
3.图示
  active 状态:当前连接对象被应用程序使用中
  Idle 空闲状态:等待应用程序使用

 

4.使用数据库连接池的目的
  在高频率访问数据库时,使用数据库连接池可以降低服务器系统压力,提升程序运行效率。(小型项目不适用数据库连接池)
5.实现 JDBCtomcatPool 的步骤
  在 web 项目的 META-INF 中存放 context.xml,在 context.xml 编写数据库连接池相关属性
  把项目发布到 tomcat 中,数据库连接池就产生了。

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource
        driverClassName="com.mysql.jdbc.Driver"  
        url="jdbc:mysql://localhost:3306/ssm"
        username="root"
        password="smallming"
        maxActive="50"    
        maxIdle="20"    
        name="test"      <!--别名,调用使用-->
        auth="Container"    <!--表示数据库连接池由tomcat管理(还可能由应用程序管理)-->
        maxWait="10000"   <!--最长时间等待,未响应后返回异常-->
        type="javax.sql.DataSource" 
    />
</Context>

6.可以在 java 中使用 jndi 获取数据库连接池中对象
  Context:上下文接口.context.xml 文件对象类型
代码:  

@WebServlet("/pool")
public class DemoServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        try {
            //获取context.xml文件对象
            Context cxt = new InitialContext();
            //获取数据库池对象
            DataSource ds = (DataSource) cxt.lookup("java:comp/env/test");
            //获取连接对象
            Connection conn = ds.getConnection();
            PreparedStatement ps = conn.prepareStatement("select * from flower");
            ResultSet rs = ps.executeQuery();
            res.setContentType("text/html;charset=utf-8");
            PrintWriter out = res.getWriter();
            while(rs.next()){
                out.print(rs.getInt(1)+"&nbsp;&nbsp;&nbsp;&nbsp;"+rs.getString(2)+"<br/>");
            }
            out.flush();
            out.close();
            rs.close();
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

  当关闭连接对象时,把连接对象归还给数据库连接池,把状态改变成 Idle

三种查询方式

1.selectList() 返回值为 List<resultType 属性控制>
  适用于查询结果都需要遍历的需求
2.selectOne() 返回值 Object
  适用于返回结果只是变量或一行数据时
3.selectMap() 返回值 Map
  适用于需要在查询结果中通过某列的值取到这行数据的需求
  Map<key,resultType 控制>
在FlowerMapper.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">
<!-- namesapce:理解成实现类的全路径(包名+类名) -->
<mapper namespace="a.b" >
    <!-- id:方法名 
        parameterType:定义参数类型
        resultType:返回值类型.        
        如果方法返回值是list,在resultType中写List的泛型,因为mybatis对jdbc封装,一行一行读取数据
    -->
    <select id="selAll" resultType="com.su.pojo.Flower">
        select id,name name123,price,production from flower
    </select>
    
    <select id="selById" resultType="int">
        select count(*) from flower
    </select>
    
    <select id="c" resultType="com.su.pojo.Flower">
        select id,name name123,price,production from flower
    </select>
    
</mapper>

  在java中:

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("myabtis.xml");
        //使用工厂设计模式
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //生产SqlSession
        SqlSession session=factory.openSession();
        
        List<Flower> list = session.selectList("a.b.selAll");
        for (Flower flower : list) {
            System.out.println(flower.toString());
        }
        
        int count = session.selectOne("a.b.selById");
        System.out.println(count);
        
        //把数据库中哪个列的值当作map的key
        Map<Object, Object> map = session.selectMap("a.b.c", "name123");
        System.out.println(map);
        
        session.close();
    }
}

<settings>标签

1.在 mybatis 全局配置文件中通过<settings>标签控制 mybatis 全局开关
2.在 mybatis.xml 中开启 log4j
  必须保证有 log4j.jar
  在 src 下有 log4j.properties

<?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>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <typeAliases>
        <package name="com.su.pojo" />
    </typeAliases>
    <!-- default引用environment的id,当前所使用的环境 -->
    <environments default="default">
        <!-- 声明可以使用的环境 -->
        <environment id="default">
            <!-- 使用原生JDBC事务 -->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="smallming"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/su/mapper/PeopleMapper.xml"/>
        <mapper resource="com/su/mapper/PeopleMapper2.xml"/>
    </mappers>
</configuration>

3.log4j 中可以输出指定内容的日志(控制某个局部内容的日志级别)
  命名级别(包级别):<mapper>namespace 属性中除了最后一个类名
    例如 namespace=”com.su.mapper.PeopleMapper” 其中包级别为com.su.mapper,需要在 log4j.propeties 中
      先在总体级别调成 Error 不输出无用信息
      在设置某个指定位置级别为 DEBUG

 

  类级别
    namespace 属性值 ,namespace 类名
  方法级别
    使用 namespace 属性值+标签 id 属性值

parameterType 属性

1. 在XXXMapper.xml中<select><delete>等标签的 parameterType 可以控制参数类型
2. SqlSession 的 selectList()和 selectOne()的第二个参数和 selectMap()的第三个参数都表示方法的参数.
  在 Mapper.xml 中可以通过#{}获取参数
    parameterType 控制参数类型
    #{}获取参数内容
      使用索引,从 0 开始 #{0}表示第一个参数
      也可以使用#{param1}第一个参数
      如果只有一个参数(基本数据类型或 String),mybatis对#{}里面内容没有要求只要写内容即可.
      如果参数是对象#{属性名}
      如果参数是 map 写成#{key}

<select id="selById" resultType="com.su.pojo.People" parameterType="int"> 
    select * from people where id=#{0} 
</select>
People p = session.selectOne("a.b.selById",2); //查询id为2的用户信息
System.out.println(p);

3. #{} 和 ${} 的区别
  #{} 获取参数的内容支持 索引获取,param1获取指定位置参数,并且 SQL 使用?占位符
  ${} 字符串拼接不使用?,默认找${内容}内容的 get/set 方法,如果写数字,就是一个数字
4. 如果在 xml 文件中出现 “<”,“>”,双引号 等特殊字符时可以使用XML 文件转义标签(XML 自身的)
  <![CDATA[ 内容 ]]>

<select id="test" resultType="com.su.pojo.People" parameterType="int">
    <![CDATA[ select * from people where id<#{0} ]]>
</select>

5. mybatis 中实现 mysql 分页写法
  ?不允许在关键字前后进行数学运算,需要在代码中计算完成后传递到 mapper.xml 中
  在 java 代码中计算

在java中:

//显示几个 
int pageSize = 2;
//第几页 
int pageNumber = 2;
//如果希望传递多个参数,可以使用对象或 map 
Map<String,Object> map = new HashMap<>(); 
map.put("pageSize", pageSize); 
map.put("pageStart", pageSize*(pageNumber-1)); 
List<People> p = session.selectList("a.b.page",map);

在PeopleMapper.xml中:

<select id="page" resultType="com.su.pojo.People" parameterType="map"> 
    select * from people limit #{pageStart},#{pageSize} 
</select>

typeAliases 别名

1.系统内置别名: 把类型全小写
2.给某个类起别名
  alias=”自定义”
mybatis.xml 中配置

<typeAliases> 
    <typeAlias type="com.su.pojo.People" alias="peo"/> 
</typeAliases>

mapper.xml 中 peo 引用 People 类

<select id="page" resultType="peo" parameterType="map"> 
    select * from people limit #{pageStart},#{pageSize} 
</select>

3.直接给某个包下所有类起别名,别名为类名,不区分大小写

mybatis.xml 中配置

<typeAliases> 
    <package name="com.su.pojo" /> 
</typeAliases>

mapper.xml 中通过类名引用

<select id="page" resultType="People" parameterType="map"> 
    select * from people limit #{pageStart},#{pageSize} 
</select>

MyBatis 实现新增

1. 概念
  功能:从应用程序角度出发,软件具有哪些功能.
  业务:完成功能时的逻辑.对应 Service 中一个方法
  事务:从数据库角度出发,完成业务时需要执行的 SQL 集合,统称一个事务.
    事务回滚.如果在一个事务中某个 SQL 执行事务,希望回归到事务的原点,保证数据库数据的完整性.
2. 在 mybatis 中默认是关闭了 JDBC 的自动提交功能
  每一个 SqlSession 默认都是不自动提交事务.
  session.commit()提交事务.
  openSession(true);自动提交.相当于setAutoCommit(true);
3. mybatis 底层是对 JDBC 的封装
  JDBC 中 executeUpdate()执行新增,删除,修改的 SQL.返回值 int,表示受影响的行数.
  mybatis 中<insert><delete><update>标签没有 resultType 属性,认为返回值都是 int
4. 在 openSession()时 Mybatis 会创建 SqlSession 时同时创建一个Transaction(事务对象),同时 autoCommit 都为 false
  如果出现异常,应该 session.rollback()回滚事务.
5. 实现新增的步骤
  在 mapper.xml 中提供<insert>标签,标签没有返回值类型

<insert id="ins" parameterType="People"> 
    insert into people values(default,#{name},#{age}) 
</insert>

  通过 session.insert()调用新增方法

People p = new People();
p.setName("新增name1");
p.setAge(88);
int
index1 = session.insert("a.b.ins", p); if(index1>0){ System.out.println("成功"); }else{ System.out.println("失败"); }

MyBatis 实现修改

  在 mapper.xml 中提供<update>标签

<update id="upd" parameterType="People"> 
    update people set name = #{name} where id = #{id} 
</update>

  编写代码

People peo = new People();
peo.setId(4);
peo.setName("王五");
int index = session.update("a.b.upd", peo);
if(index>0){
    System.out.println("成功");
}else{
    System.out.println("失败");
}
session.commit();

mybatis 实现删除

  在 mapper.xml 提供<delete>标签

<delete id="del" parameterType="int"> 
    delete from people where id = #{0} 
</delete>

  编写代码

int del = session.delete("a.b.del",3);
if(del>0){
    System.out.println("成功");
}else{
    System.out.println("失败");
}
session.commit();

 

posted @ 2020-03-31 13:23  溯鸣  阅读(265)  评论(0编辑  收藏  举报