Mybatis入门程序2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011301372/article/details/86139138

User.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">
<!--namespace 命名空间,做SQL隔离-->
<!--用户的增删改查的SQL语句在代码中通过id进行调用,如果表单特别多,每张表单的SQL语句特别多,id可能重复-->
<!--namespace 相当于又加了一层,调用的时候通过namespace加上id进行调用,避免重名的可能-->
<!--namespace起名是有规范的-->
<mapper namespace="test">
    <!--具有增删改查对应的子标签-->

    <!--id : sql语句唯一标识-->
    <!--parameterType:指定传入参数类型,是javaBean中对应属性的类型-->
    <!--resultType : 返回结果集类型,如果返回结果为集合,可以调用selectList()方法,这个方法返回的结果就是一个集合,所以映射文件中应该配置成集合泛型的类型-->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="cn.zst.domain.User">
<!--#{}占位符,起到占用的作用,如果传入的是基本类型(String long double int Boolean float等)那么 # {}中的变量名称可以随意写-->
        SELECT * from `user` WHERE id = #{id}
    </select>
    <select id ="findUserByName" parameterType="java.lang.String" resultType="cn.zst.domain.User">
      <!--  SELECT * from `user` WHERE username like #{name}-->
        <!--${}拼接符,字符串原样拼接,如果传入的参数是基本类型(String long double int boolean float等)那么${}中的变量名称必须是value-->
        <!--注意:拼接符有SQL注入的风险,所以慎重使用-->
         SELECT * from `user` WHERE username like '%${value}%'
    </select>

    <!--增加-->
    <!--如果业务需要返回数据库自增主键,可以使用SELECT LAST_INSERT_ID()-->
    <insert id="insertUser" parameterType="cn.zst.domain.User">
        <!--执行SELECT LAST_INSERT_ID()数据库函数,返回自增的主键-->
        <!--keyProperty:将返回的主键放入传入参数的id中保存,此处的传入参数为User ,-->
        <!--order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是after-->
        <!--resultType:id 类型 ,也就是在keyproperties中属性的类型-->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
<!--如果传入的是JavaBean类型,那么#{}中的变量名称必须是JavaBean中对应的属性.属性.属性.属性.属性-->
        <!--例如,User中有一个Customer的属性,customer有一个custname属性,则表示为 customer.custname-->
        INSERT into `user` (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>



    <!--删除用户-->
    <delete id="delUserById" parameterType="java.lang.Integer">
        delete from `user` WHERE id=#{id}

    </delete>

    <!--更新,根据id来跟新,因为此处传入的是两个参数,所有通过user对象传入,因为它包含所有需要的属性-->
    <update id="updateUserById" parameterType="cn.zst.domain.User" >
        UPDATE `user` set username=#{username} WHERE id=#{id}

    </update>

</mapper>

加载映射文件

    <mappers>
        <!--url的不用,需要写在绝对路径,如 D:/,,,,-->
        <!--resource 相对路径  写完,Ctrl + 左键 可以点进去-->
        <mapper resource="User.xml"/>
        <!--<mapper resource="UserMapper.xml"/>-->
        <!--使用class属性引入接口的全路径名称
        使用规则:
        1 接口的名称和映射文件名称除扩展名外要完全相同
        2 接口和映射文件要放在同一个目录下
        -->
        <mapper class="cn.zst.mapper.UserMapper" />
    </mappers>

测试文件

package cn.zst.test;

import cn.zst.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;
import java.util.List;

/**
 * Created by zst on 2019/1/8.
 */
public class UserTest {
    @Test
    public void testFindUserById() throws Exception{

        String resource="SqlMapConfig.xml";
        //通过流将核心配置文件读取出来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

        //通过工厂创建会话
        SqlSession openSession = factory.openSession();

        //第一个参数,所调用的SQL语句 = namespace+.+sql的id
        User user = openSession.selectOne("test.findUserById", 1);
        System.out.println(user);
        openSession.close();


    }




@Test
    public void testFindUserByName() throws Exception{
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = factory.openSession();

        List<User> list = openSession.selectList("test.findUserByName", "王");
        System.out.println(list);
        openSession.close();

    }


    @Test
    public void testInsertUser() throws Exception{
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = factory.openSession();

        User user = new User();
        user.setUsername("王名");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("河南郑州");

        openSession.insert("test.insertUser",user);

        //提交事务
        //如果不提交事务,则数据不能插入到数据库中
        //在Hibernate中如果要提交事务,首先要开启事务,beganTransation
        //此处Mybatis会自动开启事务,但不知道要什么时候提交事务。所以需要手动提交事务
        openSession.commit();
        //自增主键的id
        System.out.println(user.getId());

    }
    @Test
    public void testDelUserById () throws Exception{
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = factory.openSession();

        openSession.delete("test.delUserById",28);
        //提交事务
        openSession.commit();

    }
    @Test
    public void testUpdateUserById() throws Exception{
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = factory.openSession();

        User user = new User();
        user.setUsername("王志");
        user.setId(24);
        openSession.update("test.updateUserById",user);

        openSession.commit();

    }


}

  • #{} 与${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或JavaBean属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

 ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

  • parametertype与resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

  • selectOne() 和 selectList()
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

mysql 自增主键返回

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		<!-- selectKey将主键返回,需要再返回 -->
		<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
			select LAST_INSERT_ID()
		</selectKey>
	   insert into user(username,birthday,sex,address)
	    values(#{username},#{birthday},#{sex},#{address});
	</insert>

添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

mysql 使用UUID 实现主键

<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE" 
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) 
		 values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
<!--注意这里使用的order是“BEFORE”-->

Mybatis 解决JDBC编程的问题

  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可以解决此问题。

    解决:在SqlMapConfig.xml中配置数据链接池,使用链接池管理数据库链接。

  2. Sql语句卸载代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码

    解决:将sql语句配置在XXXXmapper.xml文件与java代码分离> 解决:将sql语句配置在XXXXmapper.xml文件与java代码分离

  3. 向SQL语句传参数麻烦,因为SQL与语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis 自动将java对象映射至SQL语句,通过statement 中的parameterType定义输入参数的类型

  1. 对结果集解析麻烦,SQL变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成JavaBean对象解析比较方便

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中resuleType 定义输出结果的类型。

Mybatis与Hibernate的不同

  • Mybatis与Hibernate不同,它不完全是一个ORM框架,需要开发人员自己编写SQL语句,不过Mybatis可以通过xml或者注解的方式灵活配置要运行的SQL语句,并将java对象和SQL语句映射生成最终执行的SQL,最后将SQL执行的结果再映射生成java对象。
  • Mybatis简单易学,开发人员直接编写原生态SQL,可严格控制SQL执行性能,灵活度高,适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一旦需求变化要求成果输出迅速。但是灵活的前提是Mybatis无法做到数据库无关性,如果需要支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
  • Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(如需要固定的定制化软件)如果用Hibernate开发可以节省很多代码,提高效率。

猜你喜欢

转载自blog.csdn.net/u011301372/article/details/86139138