zoukankan      html  css  js  c++  java
  • MyBatis简单使用和入门理解

    本文记录第一次使用Mybatis时碰到的一些错误和简单理解,采用的示例是Eclipse中的JAVA工程,采用XML文件定义数据库连接。

    可以使用Java JDBC API直接操作数据库,但使用框架会更便捷、高效而且还可以利用框架提供的某些强大的功能(比如事务管理),而Mybatis就是这样的一个框架。

    Mybatis主要由四大部分组成:

    ①SqlSessionFactoryBuilder

    ②SqlSessionFactory

    ③SqlSession

    ④SQL Mapper

    要想访问(操作)数据库:要建立数据库连接,要定义数据库操作方法(insert/update/delete...),要有具体的操作数据库中的表 的SQL语句,而SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession就是用来负责底层建立数据库连接、管理连接、释放连接等。对于业务层而言,关心的是:定义一个SQL语句,让Mybatis方便地把SQL语句执行后的结果 呈现给使用者,而这可以通过SQL Mapper来完成。

    SQL Mapper由两部分组成,一是:JAVA 接口,该接口中定义了 业务层 要对数据库进行何种操作;另一部分是:XML配置文件,定义了具体的数据库操作语句和映射规则。

    假设要操作数据库test中的表 t_role,t_role有三个字段:id ,role_name,和 note

    +-----------+-------------+------+-----+---------+----------------+
    | Field | Type | Null | Key | Default | Extra |
    +-----------+-------------+------+-----+---------+----------------+
    | id | bigint(20) | NO | PRI | NULL | auto_increment |
    | role_name | varchar(20) | YES | | NULL | |
    | note | varchar(20) | YES | | NULL | |
    +-----------+-------------+------+-----+---------+----------------+

    该表对应的POJO类如下:

    package chapter2.pojo;
    
    public class Role {
        private Long id;
        private String roleName;
        private String note;
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getRoleName() {
            return roleName;
        }
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
        public String getNote() {
            return note;
        }
        public void setNote(String note) {
            this.note = note;
        }
        
        @Override
        public String toString() {
            return "id:" + id + ", roleName:" + roleName + ", note:" + note;
        }
    }
    View Code

    JAVA接口中定义的一些操作如下:

    package chapter2.mapper;
    import
    java.util.List; import java.util.Map; import chapter2.pojo.Role; public interface RoleMapper { public Role getRole(Long id); public int deleteRole(Long id); public int insertRole(Role role); public List<Role> findRoleByMap(Map<String, String> params); }

    与该接口对应,定义的具体操作数据库的配置文件RoleMapper.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="chapter2.mapper.RoleMapper">
    
    <resultMap type="chapter2.pojo.Role" id="roleMap">
    <id property="id" column="id"/><!-- primary key -->
    <result property="roleName" column="role_name"/><!-- 普通列的映射关系 -->
    <result property="note" column="note"/>
    </resultMap>
    
    
        <select id="getRole" parameterType="long" resultType="Role">
            select id, role_name as roleName, note from t_role where id = #{id}
        </select>
        <insert id="insertRole" parameterType="Role">
            insert into t_role(role_name,note) values(#{roleName},#{note})
        </insert>
        <delete id="deleteRole" parameterType="long">
            delete from t_role where id = #{id}
        </delete>
        
        <select id="findRoleByMap" parameterType="map" resultMap="roleMap">
            select id,role_name,note from t_role
            where role_name like concat('%', #{roleName},'%')
            and note like concat('%',#{note},'%')
        </select>
    </mapper>

    然后,就可以用SqlSessionFactory创建SqlSession,SqlSession获取相应的RoleMapper实例,再使用RoleMapper实例调用RoleMapper接口中定义的方法,最终由Mybatis根据 RoleMapper.xml配置文件将 方法 与 映射成具体的数据库操作语句,最终访问数据库。

    使用SqlSessionFactoryBuilder 根据 mybatisConfig.xml中配置的 dataSource创建SqlSessionFactory,再使用SqlSessionFactory创建SqlSession,代码如下:

    package chapter2.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    public class SqlSessionFactoryUtil {
        private static SqlSessionFactory sqlSessionFactory = null;
        private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;
        private SqlSessionFactoryUtil() {}
        
        public static SqlSessionFactory initSqlSessionFactory() {
            String resource = "mybatisConfig.xml";
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream(resource);
            }catch(IOException ex) {
                Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SEVERE, null, ex);
            }
            synchronized (CLASS_LOCK) {
                if(sqlSessionFactory == null) {
                    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                }
            }
            return sqlSessionFactory;
        }
        
        public static SqlSession openSqlSession() {
            if(sqlSessionFactory == null)
            {
                initSqlSessionFactory();
            }
            return sqlSessionFactory.openSession();
        }
    }
    View Code

    报错:

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in 
    class path resource [detect/xx/xx/applicationContext.xml]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException:
    Failed to parse config resource: class path resource [detect/xx/xx/mybatisConfig.xml]; nested exception is org.apache.ibatis.builder.BuilderException:
    Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance.
    Cause: org.xml.sax.SAXParseException; lineNumber: 18; columnNumber: 142; 元素内容必须由格式正确的字符数据或标记组成。

    从上面错误可看出,若不能正确地创建sqlSessionFactory,有可能是 mybatisConfig.xml配置有错,而 mybatisConfig.xml里面 通过 <mapper>标签指定了 xxxMapper.xml SQL Mapper Configuration。

    因此,也要检查 xxxMapper.xml 中写的 SQL 语句 是否正确

    用户程序根据SqlSession来获取RoleMapper(第20行),然后调用里面定义的方法操作数据库,从这里也可以看出,我们只需要定义好接口,在XML配置文件中定义SQL操作语句,就可以访问数据库了:代码如下:

    package chapter2.main;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.ibatis.session.SqlSession;
    
    import chapter2.mapper.RoleMapper;
    import chapter2.pojo.Role;
    import chapter2.util.SqlSessionFactoryUtil;
    
    public class Chapter2Main {
        public static void main(String[] args)throws IOException {
            SqlSession sqlSession = null;
            
            try {
                sqlSession = SqlSessionFactoryUtil.openSqlSession();
                RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
                
                Role role = new Role();
                role.setRoleName("testName");
                role.setNote("testNote");
                roleMapper.insertRole(role);
                //roleMapper.deleteRole(1L);
                sqlSession.commit();
                
                Map<String, String> paramsMap = new HashMap<>();
                paramsMap.put("roleName", "me");
                paramsMap.put("note", "no");//与sql语句中的 #{note} #{roleName}一致
                List<Role> result = roleMapper.findRoleByMap(paramsMap);
                for (Role role2 : result) {
                    System.out.println(role2);
                }
                
            }catch(Exception e) {
                System.out.println(e);
                sqlSession.rollback();
            }finally {
                if(sqlSession != null)
                    sqlSession.close();
            }
            
        }
    }
    View Code

    Mybatis配置数据库连接: mybatisConfig.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"    
     3 "http://mybatis.org/dtd/mybatis-3-config.dtd">
     4 <configuration>
     5     <properties resource="jdbc.properties">
     6     </properties>
     7     <typeAliases>
     8         <typeAlias alias="Role" type="chapter2.pojo.Role" />
     9     </typeAliases>
    10 
    11     <environments default="development">
    12         <environment id="development">
    13             <transactionManager type="JDBC">
    14                 <property name="autoCommit" value="false" />
    15             </transactionManager>
    16             <dataSource type="POOLED">
    17                 <property name="driver" value="${driver}" />
    18                 <property name="url" value="${url}" />
    19                 <property name="username" value="${username}" />
    20                 <property name="password" value="${password}" />
    21             </dataSource>
    22         </environment>
    23     </environments>
    24 
    25     <mappers>
    26         <mapper resource="chapter2mapperRoleMapper.xml" />
    27     </mappers>
    28 </configuration>

    Mybatis的XML配置文件定义了许多配置标签:比如 <configuration> <properties> <settings> <typeAliases> ....等标签。

    这些标签是有层次结构的,顺序不能乱。比如,<properties>标签应该放在 <typeAliases> 标签前面。

    上面的第5行<properties>标签 通过  resource 指定一个外部jdbc配置文件,这样在16-21行配置 数据源 的时候,就可以使用 变量 来引用 外部jdbc配置文件中定义的值了,从而方便切换数据库配置。

    外部jdbc配置文件如下:

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test
    username=root
    password=xxxx

    下面来重点解释:操作数据库的XML配置文件RoleMapper.xml 和 接口RoleMapper 以及POJO类RoleMapper之间的一些关系:

    RoleMapper 接口中定义的getRole方法:

    public Role getRole(Long id);

    RoleMapper.xml配置文件中与该方法对应的SQL语句:

        <select id="getRole" parameterType="long" resultType="Role">
            select id, role_name as roleName, note from t_role where id = #{id}
        </select>

    id 用来唯一标明这条 select 语句。它与RoleMapper.xml中 <mapper namespace>标签内容组合在一起,唯一标识了 这条 select 操作语句。这里的resultType="Role","Role"是在mybatisConfig.xml中定义的别名。

    <mapper namespace="chapter2.mapper.RoleMapper">
    
    public Role getRole(Long id);
    
    <select id="getRole" parameterType="long" resultType="Role">
    
    
    id 的值getRole 就是接口RoleMapper中 定义的 getRole方法名
    parameterType 就是getRole方法的参数类型
    resultType 就是执行SQL语句后返回的结果,把结果 封装 成POJO类 Role 类型---这也是getRole方法的返回类型。而方法的参数 会传递给#{id}

    几种传 多个参数 给SQL语句的方法:

    一,通过Map对象传参数

    RoleMapper中定义的findRoleByMap方法

        public List<Role> findRoleByMap(Map<String, String> params);
        <select id="findRoleByMap" parameterType="map" resultMap="roleMap">
            select id,role_name,note from t_role
            where role_name like concat('%', #{roleName},'%')
            and note like concat('%',#{note},'%')
        </select>

    当我们需要根据多个 参数 查找数据库时,且查找的结果也可能返回多条记录时,就使用上面的配置。

    paramterType="map",传入一个map对象作为select语句的参数,其中map中的每个元素的key 对应 while子句中的#{roleName}#{note}

    由于这里的while子句 只根据 两个参数 来查询,因此map的长度为2. 而map的value,则是 查询的条件的值。

                Map<String, String> paramsMap = new HashMap<>();
                paramsMap.put("roleName", "me");//value是要满足的条件值   while note = "me"
                paramsMap.put("note", "no");//Key与sql语句中的 #{note} #{roleName}一致
                List<Role> result = roleMapper.findRoleByMap(paramsMap);

    select id,role_name,note from t_role   where role_name like concat('%', ?,'%')   and note like concat('%',?,'%')

    比如:select id,role_name,note from t_role   where role_name like concat("me")   and note like concat("no")

    resultMap指明了返回的“结果”的形式:resultMap=roleMap。resultMap的定义如下:(可理解为:resultMap的key是 属性名或者字段名,而value则是 相应的 结果值)

    <resultMap type="chapter2.pojo.Role" id="roleMap">
    <id property="id" column="id"/><!-- primary key -->
    <result property="roleName" column="role_name"/><!-- 普通列的映射关系 -->
    <result property="note" column="note"/>
    </resultMap>

    <id property="id" column="id" 表明 id 是 t_role表的主键,主键的列名是 "id"

    <result property="roleName" colum="role_name"/> 表明:roleName是POJO类的属性名,"role_name"是数据库表t_role的列名,将二者对应起来。

    二,使用参数注解的方式传递多个参数

    或者使用更“易懂“的映射方法:----参数注解

    RoleMapper接口里面定义的方法:

        public List<Role> findRoleByAnnotation(@Param("roleName")String roleName, @Param("note")String note);

    RoleMapper.xml配置文件里面的定义的SQL语句:这里就没有 paramterType 来定义查询的参数了

            <select id="findRoleByAnnotation"resultMap="roleMap">
            select id,role_name,note from t_role
            where role_name like concat('%', #{roleName},'%')
            and note like concat('%',#{note},'%')
        </select>

    客户端 调用方法:这里,就可以不用HashMap封装多个待查询的参数了。

    List<Role> res = roleMapper.findRoleByAnnotation("me", "no");
    for (Role role2 : res) {
        System.out.println(role2);
        }

    三,使用JAVA Bean对象传递参数:

    RoleMapper.xml配置文件里面的定义的SQL语句:

        <select id="findRoleByParam" parameterType="chapter2.pojo.RoleParam"
            resultMap="roleMap">
            select id,role_name,note from t_role
            where role_name like
            concat('%', #{roleName},'%')
            and note like concat('%',#{note},'%')
        </select>

    RoleMapper.java接口方法:

        public List<Role> findRoleByParam(RoleParam role);

    客户端调用执行:

                RoleParam rp = new RoleParam();
                rp.setNote("note");
                rp.setRoleName("test");
                List<Role> roles = roleMapper.findRoleByParam(rp);

    批量插入操作:

    RoleMapper.xml配置文件里面的定义的SQL语句:

        <insert id="insertBatch"  useGeneratedKeys="true" parameterType="java.util.List">
            insert into t_role(role_name, note)
            values
            <foreach collection="list" item="item" index="index"
                separator=",">
                (#{item.roleName},#{item.note})
            </foreach>
        </insert>

    useGeneratedKeys="true" 表明使用数据库表中自带的主键自增策略。在文章所述的t_role表的结构中, id 是自增的主键,但是这里的批量插入操作,并不需要显示的插入 id 的值。

    待插入的每条记录值 放在 java.util.List 对象中保存,通过 foreach 循环遍历,"item"代表遍历到的每条记录---即每个Role对象, 通过 #{item.roleName} 和 #{item.note} 取出Role对象属性值---即每个表的字段值。


    RoleMapper.java接口方法:

        public void insertBatch(List<Role> roleList);

    客户端调用执行:(记得最终 调用 commit() 方法进行提交)

                sqlSession = SqlSessionFactoryUtil.openSqlSession();
                RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
                
                Role role = new Role();
                role.setRoleName("testName");
                role.setNote("testNote");
                
                Role role2 = new Role();
                role2.setRoleName("xx");
                role2.setNote("notexx");
                
                List<Role> roleList = new ArrayList<>();
                roleList.add(role2);
                roleList.add(role2);
                
                roleMapper.insertBatch(roleList);
                System.out.println("insert finished");
                sqlSession.commit();
  • 相关阅读:
    面向对象的三大特征
    前端基础----CSS基础概要(四)
    前端基础----CSS概要(三)
    前端基础----CSS概要(二)
    前端基础----CSS基础概要(一)
    计算机基础----常用的快捷键(一)
    前端基础------HTML概要(一)
    计算机基础---常用的应用软件
    计算机的分类
    计算机基础---硬件的组成
  • 原文地址:https://www.cnblogs.com/hapjin/p/7290876.html
Copyright © 2011-2022 走看看