MyBatis学习笔记(二)

目录

一、Mapper代理开发

二、Mapper程序(CRUD)

1.思路

2.源码

编写dao接口,StudentDao.java

配置映射文件(CRUD语句),StudentMapper.xml

指定映射文件位置SqlMapConfig.xml

测试文件,TestMapperDemo.java

三、小结


一、Mapper代理开发

传统dao模式下存在大量模板方法(selectOne,selectList,insert,delete,update),不灵活。调用SqlSession方法的时候,存在硬编码(将数据直接嵌入到程序或其他可执行对象的源代码中,通常表示不变的信息,不易维护)。MyBatis学习笔记(二)

二、Mapper程序(CRUD)

1.思路

  • 编写dao接口:存放方法声明
  • 映射文件(StudentMapper.xml):实现接口
    • StudentMapper.xml的namespace和接口路径一致MyBatis学习笔记(二)
    • StudentDao.java的方法名和StudentMapper.xml的id名一致
    • StudentDao.java传入参数类型、返回值类型和StudentMapper.xml的一致MyBatis学习笔记(二)

2.源码

编写dao接口,StudentDao.java

package com.jc.dao;
import com.jc.entity.Student;
import java.util.List;

public interface StudentDao {
    public Student findById(int id);
    public List<Student> findAll();
    public void add(Student student);
    public void update(Student student);
    public void delete(int id);
}

配置映射文件(CRUD语句),StudentMapper.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">
<!-- 命名空间,可以对sql进行分类的一个管理 -->
<mapper namespace="com.jc.dao.StudentDao">

    <select id="findById" parameterType="int" resultType="com.jc.entity.Student">
      select * from student where sid=#{0}
   </select>
    <select id="findAll" resultType="com.jc.entity.Student">
        select * from student
    </select>
    <!--返回自增主键方法一-->
    <insert id="add" parameterType="com.jc.entity.Student" useGeneratedKeys="true" keyProperty="sid">
        insert into student(sname,sex,password,age)
        values (#{sname},#{sex},#{password},#{age});
    </insert>
    <!--返回自增主键方法二-->
    <!--<insert id="add" parameterType="com.jc.entity.Student">-->
        <!--/*-->
        <!--selectKey:主键返回-->
        <!--keyProperty:实体类中的主键属性-->
        <!--resultType:主键的数据类型-->
        <!--order:指定selectKey何时执行-->
        <!--*/-->
        <!--<selectKey keyProperty="sid" resultType="int" order="AFTER">-->
            <!--SELECT LAST_INSERT_ID()-->
        <!--</selectKey>-->
        <!--insert into student(sname,sex,password,age)-->
        <!--values (#{sname},#{sex},#{password},#{age});-->
    <!--</insert>-->

    <delete id="delete" parameterType="int">
        delete from student where sid=#{0}
    </delete>
    <update id="update" parameterType="com.jc.entity.Student">
        update student set sname=#{sname},sex=#{sex},password=#{password},age=#{age} where sid=#{sid}
    </update>
</mapper>

指定映射文件位置SqlMapConfig.xml

<!--指定映射文件位置-->
<mappers>
    <mapper resource="StudentDao.xml"></mapper>
    <!--在原来的代码中加入Mapper映射-->
    <mapper resource="StudentMapper.xml"></mapper>
</mappers>

测试文件,TestMapperDemo.java

ps:注解(加上是不是感觉代码清晰简洁多了)

  • @Before: 前置通知, 在方法执行之前执行
  • @After: 后置通知, 在方法执行之后执行
  • @Test:Java单元测试
package com.jc.testStudent;

import com.jc.dao.StudentDao;
import com.jc.entity.Student;
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.After;
import org.junit.Before;
import org.junit.Test;

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

public class TestMapperDemo {
    SqlSession sqlSession=null;
    StudentDao studentDao=null;
    @Before
    public void begin() throws IOException {
        //1、通过IO读取配置文件
        InputStream inputStream= Resources.getResourceAsStream("SqlMapConfig.xml");
        //2、创建会话工厂,传入MyBatis配置文件信息
        SqlSessionFactory sessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
        //3、通过会话工厂获取会话
        sqlSession=sessionFactory.openSession(true);
        studentDao = sqlSession.getMapper(StudentDao.class);
    }
    @After
    public void end(){
        //5、关闭
        sqlSession.close();
    }
    
    //    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    
    @Test
    //根据id查询
    public void testFindById() throws IOException {
        Student student = studentDao.findById(13);
        System.out.println(student.getSid()+"\t"+student.getSname()+"\t"+student.getSex()+"\t"+student.getAge());
    }
    @Test
    //查询全部
    public void testFindAll() throws IOException {
        List<Student> list = studentDao.findAll();
        for (Student student : list) {
            System.out.println(student.getSid()+"\t"+student.getSname()+"\t"+student.getSex()+"\t"+student.getAge());
        }
    }
    @Test
    //插入
    public void add() throws IOException{
        Student student=new Student();
        student.setSname("zzzz");
        student.setSex("男");
        student.setPassword("hcdi8y38h");
        student.setAge(166);
        studentDao.add(student);
        System.out.println("自增的id为:"+student.getSid());
    }
    @Test
    //删除
    public void delete() throws IOException{
        studentDao.delete(15);
    }
    @Test
    //修改
    public void update() throws IOException {
        Student student=new Student();
        student.setSid(14);
        student.setSname("zg");
        student.setSex("女");
        student.setPassword("123");
        student.setAge(88);
        StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
        studentDao.update(student);
    }
}

三、小结

Q:当时写测试代码时,为了图方便把StudentDao方法放到外面来了,这样就不用在每个方法中都写一遍,结果就报了空指针错误

MyBatis学习笔记(二)

java.lang.NullPointerException
	at com.jc.testStudent.TestMapperDemo.<init>(TestMapperDemo.java:36)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:195)
	at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:244)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:241)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

A:sqlSession没有创建,方法外的代码比before里面先执行,所以会出现找不到sqlSession,空指针异常。

可以将该方法写在before注解的方法中,StudentDao定义为全局变量,这样就可以了

MyBatis学习笔记(二)

 

上一篇:jedis客户端操作


下一篇:JUnit单元测试