目录
配置映射文件(CRUD语句),StudentMapper.xml
一、Mapper代理开发
传统dao模式下存在大量模板方法(selectOne,selectList,insert,delete,update),不灵活。调用SqlSession方法的时候,存在硬编码(将数据直接嵌入到程序或其他可执行对象的源代码中,通常表示不变的信息,不易维护)。
二、Mapper程序(CRUD)
1.思路
- 编写dao接口:存放方法声明
- 映射文件(StudentMapper.xml):实现接口
- StudentMapper.xml的namespace和接口路径一致
- StudentDao.java的方法名和StudentMapper.xml的id名一致
- StudentDao.java传入参数类型、返回值类型和StudentMapper.xml的一致
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方法放到外面来了,这样就不用在每个方法中都写一遍,结果就报了空指针错误
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定义为全局变量,这样就可以了