当前位置:首页 > 图灵资讯 > 技术篇> Mybatis总结

Mybatis总结

发布时间:2023-05-16 09:26:41
1.namespace的作用

在mybatis中,命名空间除了隔离sql外,还具有定义mapper接口地址的特殊功能。

问题:

java面向接口编程语言,不使用接口编程。数据库的操作应定义一些操作接口,如用户添加、用户删除、用户查询等。,并调用dao接口完成数据库操作。

Mybatis总结_sql

上面的代码应该调用selectone、selectList,人工判断完全不方便。selectlist和selectone方法参数是object类型。如果程序员在编码中设置参数错误,则在编译阶段不会报告错误。假设:mybatis封装能否包装 方法实现体,方法名:和mapper.statementid在xml中保持一致。输入参数类型的方法:和mapper.parametertype在xml中的指定类型相同。方法返回值:可根据dao接口进行返回 返回值的类型决定是调用selectone还是selectlist,类型和mapper.resulttype类型在xml中保持不变 一致使用mybatis提供动态代理来生成接口来实现对象。mapper.xml知道mapper.java,通过namespace配置对应关系。

改为mapper 接口实现:

第一步:定义mapper.xml

Mapper.用原来的xml文件不变。

第二步:定义mapper 接口
///mapper接口路径和mapper.namespace在xml中一致publice interface UserMapper {    //根据mapper.statement定义在xml中    //方法名:和mapper.statementid在xml中的id一致    //输入参数:和mapper.parametertype在xml中一致    //输入结果:和mapper.resultttype在xml中一致    public  User findUserById(int id)throws Exception;    ////自定义条件查询用户信息    public List<User> findUserList(User user)throws Exception;    ///查询用户列表输出mapp    public List<Map> findUserListReturnMap(User user)throws Exception;    ///使用resultmap查询用户列表    public List<User> findUserListResultMap(User user)throws Exception;    ///插入用户    public void insertUser(User user)throws Exception;    /////查询用户列表总数    public int findUserCount(User user)throws Exception;    ////查询用户传mapp    public List<User>  findUserListByMap(Map map)throws Exception;}

界面定义具有以下特点:

1、Mapper接口方法名和mapper.定义在xml中的每个sqlid都是相同的

2、输入参数类型和Mapper接口方法.定义在xml中的每个sql parametertype类型相同

3、输出参数类型和Mapper接口方法.在xml中定义的每个sqlresulttype类型相同

第三步:修改namespace

Mapper.xml映射文件中的namepace改为以下内容:

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

namespace修改后是maper接口的地址。

第四步:通过maper接口调用statementent:
public class UserMapperTest {    SqlSessionFactory sqlSessionFactory;    @Before    public void setUp() throws Exception {        // 创建会话工厂        // SqlsessionFactory创建的会话工厂        String resource = "SqlMapConfig.xml";        InputStream inputStream = Resources.getResourceAsStream(resource);        // SqlsessionFactory创建的会话工厂        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);    }    @Test    public void testFindUserById() throws Exception {            SqlSession sqlSession = sqlSessionFactory.openSession();            //////生成mapper接口的代理对象            UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);            //调用 mapper接口的方法            User user = userMapper.findUserById(1);            System.out.println(user);    }    @Test    public void testInsertUser() throws Exception {            SqlSession sqlSession = sqlSessionFactory.openSession();            //////生成mapper接口的代理对象            UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);            //构造查询条件            User user_insert  = new User();            user_insert.setUsername(张三四);            user_insert.setSex("1");            //调用 mapper接口的方法            userMapper.insertUser(user_insert);            ///提交事务            sqlSession.commit();            sqlSession.close();    }    }
session.getMapper(UserMapper.class)生成代理对象作为UserMaper的接口来实现对象。

Mybatis总结_xml_02

总结:Mapper接口动态代理对象生成规则:1、mapper接口路径和mapper.namespace在xml中一致2、方法名:和mapper.statementid在xml中的id一致3、输入参数:和mapper.parametertype在xml中一致4、输入结果:和mapper.xml中的resulttype一致两个文件:mapper.xml(mapper映射文件)和mapper.java(mapper接口文件)

2.SqlMapConfig.xml配置内容

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型名称)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

(环境子属性对象)

(事务管理)

(数据源)

mappers(映射器)

properties(属性)

SqlMapConfig.java属性文件中的配置信息如下:

dbaspath在classpath下定义.properties文件,

jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatisjdbc.username=rootjdbc.password=mysql

引用如下:

<properties resource="db.properties" />    <environments default="development">        <environment id="development">            <transactionManager type="JDBC" />            <dataSource type="POOLED">                <property name="driver" value="${jdbc.driver}" />                <property name="url" value="${jdbc.url}" />                <property name="username" value="${jdbc.username}" />                <property name="password" value="${jdbc.password}" />            </dataSource>        </environment>    </environments>

mappersMapper配置的几种方法:<mapper resource=" " />使用相对于类路径的资源,如:<mapper resource="sqlmap/user.xml" /><mapper url=" " />使用完全有限的路径如下:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\user.xml" /><mapper class=" " />使用mapper接口类路径如下:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>注:该方法要求mapper接口名称与mapper映射文件名称相同,并将其放在同一目录中。<package name=""/>注册指定包下的所有mapper接口如下:<package name="cn.itcast.mybatis.mapper"/>注:该方法要求mapper接口名称与mapper映射文件名称相同,并放置在同一目录中。

3.Mapper.xml

操作数据库的sql定义在映射文件中,每个sql都是statement,映射文件是mybatis的核心。

parametertype输入类型

#{}与${}

#{}实现的是将参数值设置在preparestatement中的预处理语句中,sql语句中#{}表示占位符。

<!-- 根据id查询用户信息 --><select id="selectUserById"  parameterType="int" resultType="user">select * from user where id = #{id}</select>

使用占位符#{}可以有效防止sql注入,使用时不需要注意参数值的类型。mybatis会根据参数值的类型调用不同的statement来设置参数值。可以想象,如果参数值是字符串,则自动映射生成的sql中的参数值两侧自动有单引号,如果参数值是数字型,则自动映射生成的sql中的参数值两侧没有单引号。

注:当传输单个值时,#{}中的参数名称通常与maper接口的形状参数名称相同,也可设置为任意值。

${}不同于#{},${}是将参数值不加修饰的拼接在sql中,相当于用jdbc的statement拼接sql,使用${}不能防止sql注入,但有时使用${}会非常方便,如下:

<!-- 用户信息根据名称模糊查询 --><select id="selectUserByName" parameterType="string" resultType="user">   select * from user where username like '%${value}%'</select>

如果在这个例子中使用#{},输入的字符串中必须有%,而%是人工拼接在参数中,这显然有点麻烦。如果使用${}在sql中拼接为%,则调用mapper接口传输参数要方便得多。

//如果使用占位符号,则必须人为添加%

List<User> list = userMapper.selectUserByName(%管理员%);

//如果使用${}原始符号,则不需要人为添加参数的%

List<User> list= userMapper.selectUserByName(管理员);

再比如order by排序,如果列名通过参数传输到sql,则根据传输的列名进行排序,则应写为:

ORDER BY ${columnName}

如果使用#{},此功能将无法实现。

注意:${}不能防止sql注入,对系统安全影响很大。如果使用${},建议用户尽量不要自动填写输入参数,即使用户需要填写,也要检查填写的数据,以确保安全。

另外,当传递单个值时,${}中填写的参数名称经测试填写value是不错的。

传输pojo对象

Mybatis使用ognl表达式来分析对象字段的值,例如:

 

<!—pojo对象综合查询用户信息 -->    <select id="selectUserByUser" parameterType="user" resultType="user">       select * from user where id=#{id} and username like '%${username}%'    </select>

 

user对象中的字段名称标注在上面的大括号上。

测试:

public void testselectUserByUser()throws Exception{        //获得session        SqlSession session = sqlSessionFactory.openSession();        //受限mapper接口实例        UserMapper userMapper = session.getMapper(UserMapper.class);        ///构造查询条件user对象        User user = new User();        user.setId(1);        user.setUsername(管理员);        /////传输user对象查询用户列表        List<User> list = userMapper.selectUserByUser(user);        //关闭sesssion        session.close();    }

异常测试:

在Sql中字段名输入错误后进行测试,username输入dusername测试结果报错:

org.apache.ibatis.exceptions.PersistenceException: ### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'dusername' in 'class cn.itcast.mybatis.po.User'### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'dusername' in 'class cn.itcast.mybatis.po.User'

传输hashmap

Sql映射文件定义如下:

<!-- hashmap综合查询用户信息

<selectid="selectUserByHashmap"parameterType="hashmap"resultType="user">

select * from user where id=#{id} and username like '%${username}%'

</select>

hashmapkey标有上面的红色。

测试:

public void testselectUserByHashmap()throws Exception{        //获得session        SqlSession session = sqlSessionFactory.openSession();        //受限mapper接口实例        UserMapper userMapper = session.getMapper(UserMapper.class);        ///Hashmap对象的构造查询条件        HashMap<String, Object> map = new HashMap<String, Object>();        map.put("id", 1);        map.put("username", “管理员”;                ////传输Hashmap对象查询用户列表        List<User> list = userMapper.selectUserByHashmap(map);        //关闭sesssion        session.close();    }

异常测试:

map中的key与sql中分析的key不一致。

测试结果没有报错,只是通过key获得值为空。

resultType(输出类型)输出简单类型

参考getnow输出日期类型,看下面的例子输出整形:

文件

<!-- 获取用户列表总数 --><select id="selectUserCount" parameterType="user" resultType="int">   select count(1) from user</select>

Mapper接口

public int selectUserCount(User user) throws Exception;

调用:

public void testselectUserCount() throws Exception{        //获得session        SqlSession session = sqlSessionFactory.openSession();        ///获得mapper接口实例        UserMapper userMapper = session.getMapper(UserMapper.class);            User user = new User();        user.setUsername(管理员);        ////传输Hashmap对象查询用户列表        int count = userMapper.selectUserCount(user);                ///使用session实现        //int count = session.selectOne("cn.itcast.mybatis.mapper.UserMapper.selectUserCount", user);        //关闭sesssion        session.close();    }

总结:

必须查询输出简单类型的结果集有一个记录,最后将第一个字段的值转换为输出类型。

使用session的selectone可以查询单个记录。

Sql片段

可在Sql中提取重复的Sql,使用时可引用include,最终达到Sql重用的目的,如下:

<!-- pojo综合查询用户信息 -->    <select id="selectUserByUser" parameterType="user" resultType="user">        select * from user         <where>         <if test="id!=null and id!=null and id!=''">        and id=#{id}        </if>        <if test="username!=null and username!=''">        and username like '%${username}%'        </if>        </where>    </select>

提取where条件:

<sql id="query_user_where">    <if test="id!=null and id!=''">        and id=#{id}    </if>    <if test="username!=null and username!=''">        and username like '%${username}%'    </if>    </sql>

使用include引用:

<select id="selectUserByUser" parameterType="user" resultType="user">        select * from user         <where>         <include refid="query_user_where"/>        </where>    </select>

注:如果引用其他mapper.在引用xmlsql片段时,需要添加namespace,如下:

<includerefid="namespace.sql片段”/sql片段>

resultMap

当输出pojo的字段与sql查询的字段名称不对应时,如果您想使用此pojo类作为输出类型,则需要使用resultmap。

此外,resultmap还解决了一对一关联查询、一对多关联查询等常见需求。

创建Person类:

public class Person {    private int id;    private String name;// 用户姓名,与User表的字段名称不同    private String sex;// 性别    private Date birthday;// 出生日期    private String addr;// 地址,与User表的字段名称不同    private String detail;// 详细信息    private Float score;// 成绩get//set。。。。。

resultmapp定义

mapper.resultMapp在xml文件中定义:

<!-- resultmap定义 -->    <resultMap type="cn.itcast.mybatis.po.Person" id="personmap">       <id property="id" column="id"/>       <result property="name" column="username" />       <result property="addr" column="address" />    </resultMap>

<id />:这个属性表示查询结果集的唯一标志,非常重要。如果多个字段是复合的唯一约束,则定义多个字段<id />。

Property:表示person属性。

Column:表示sql查询的字段名。

将Column和property放在一起,将sql查询的字段映射到指定的pojo属性上。

<result />:普通结果,即pojo属性。

这里只定义了sql查询到的字段与pojo属性名不一致,并通过后面的测试自动映射pojo属性名与sql字段相同。

Mapper.xml定义

<!-- 获取用户列表返回resultmapp -->    <select id="selectUserListResultMap" resultMap="personmap">        select * from user    </select>

使用resultmap指定上面定义的personmap。

Mapper接口定义

public List<Person> selectUserListResultMap() throws Exception;

实际返回类型为Person类型。

测试

public void testselectUserListResultMap() throws Exception{        //获得session        SqlSession session = sqlSessionFactory.openSession();        //受限mapper接口实例        UserMapper userMapper = session.getMapper(UserMapper.class);            User user = new User();        user.setUsername(管理员);        ///查询用户列表返回resultmapp        List<Person> list = userMapper.selectUserListResultMap();        System.out.println(list);        //关闭sesssion        session.close();    }
上一篇 javaswing如何给文本框赋值 java文本框设置字体
下一篇 mac java安装目录查找 mac安装jdk路径

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: Java教程Java基础Java编程技巧面试题Java面试题