MyBatis学习总结(二)

Mybatis进行CRUD

之前已经配置了MyBatis的使用环境以及其它一切所需要的基础文件,但是一直没说这个东西究竟时怎么样来操作数据库的。上一次的总结最后的Test类就是干这件事情的。

基础方式

在测试类的方法中,显然是要读取conf.xml文件的,然后用这个IO流创建一个SqlSessionFactory(SqlSessionFactoryBuilder().build(reader),build的第二个参数可以指定数据库环境,默认使用environments的default指定的);用SqlSessionFactory的openSession方法还能构造一个SqlSession实例。

Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

讲了这么多,其实这个SqlSession实例就相当于JDBC的Connection,不过干的事情更多些:SqlSession不止是声明了数据库信息,它的创建所依据的那个conf.xml文件中还声明了映射文件,所以所有即将用到的sql语句都是SqlSession实例所直接能够使用的;而JDBC中所有的sql语句都要自己现场手写,不易管理、修改起来很不方便。

在Mapper.xml中,每一个sql语句都是由namespace和id来唯一标识。而这里增删改查的方式就是直接定位到每一个Mapper.xml中的语句来实现数据库操作,定位方法是直接将这两个东西弄成一个String:

String statement="shopkeeper.personMapper."+"queryAll";

增删改查是调用SqlSession实例的对应的方法,其中第一个参数必须是唯一标识statement,后继的参数如同Mapper.xml文件中的一样如果没有就不写,要有的话只能有一个(多个就封装成对象);返回值稍作改变,Mapper.xml中无论返回值有多少个,都只写一个的情况,但是Java语言不能这样,要视情况改变(其实全写List也行,反正原理都是从游标读,然后返回值的多少其实是取决于你调用的SqlSession的方法,例如selectOne和selectLst):

Person person=sqlSession.selectOne(statement,1);
List<Person> persons=sqlSession.selectList(statement);
int count=sqlSession.insert(statement,person);
int count=sqlSession.delete(statement,3);
int count=sqlSession.update(statement,person);

由于我使用的事务方式是JDBC,增删改操作还是要commit的,做法为调用SqlSession.commit()方法。

完整的方法如下:

public static void queryPersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="shopkeeper.personMapper.queryPersonById";

Person person=sqlSession.selectOne(statement,1);

System.out.println(person);
sqlSession.close();
reader.close();
}

public static void queryAllPerson() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="shopkeeper.personMapper."+"queryAll";

List<Person> persons=sqlSession.selectList(statement);

System.out.println(persons);
sqlSession.close();
reader.close();
}

public static void addPerson() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="shopkeeper.personMapper."+"addPerson";

Person person=new Person(19,"刘茜元",3);
int count=sqlSession.insert(statement,person);
sqlSession.commit();

System.out.println("增加了"+count+"个人");
sqlSession.close();
reader.close();
}

public static void deletePersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="shopkeeper.personMapper."+"detelePersonById";

int count=sqlSession.delete(statement,3);
sqlSession.commit();

System.out.println("删除了"+count+"个人");
sqlSession.close();
reader.close();
}

public static void updatePersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="shopkeeper.personMapper."+"updatePerson";

Person person=new Person();
person.setId(3);
person.setName("刘闹闹");
person.setAge(19);
int count=sqlSession.update(statement,person);
sqlSession.commit();

System.out.println("更新了"+count+"个人");
sqlSession.close();
reader.close();
}

mapper动态代理方式CRUD

也叫接口开发。

在基础方式中说JDBC不好时,点名批评了JDBC每一个sql语句都要手写,但是其实基础方式里面也是要手写每一个statement的,只不过是将sql语句简化为了namespace+id了。

但是我们要严于律己,仅仅做到这方面是远远不够的,最好能够达到直接调用方法就能指哪打哪。mapper动态代理就是干的这件事。

总的来说,Mapper动态代理的思路就是将Mapper.xml中的sql语句变成接口中的方法,约定之前的namespace成为接口名称,每一个id变成方法名,具体是怎么实现的就是MyBatis底层的事情了。

那么,这些接口就需要满足以下几个要求:

接口名为namespace;

方法名为id值;

输入的参数和mapper.xml的parameterType一致;

返回值如果是查询就必须和resultType一致,如果你想要得到增删改操作成功的结果数量,就可以写成int,如果不想要就写void。

有多个Mapper.xml文件就实现多个接口。匹配的过程是根据接口名找到mapper. xml文件,根据接口的方法名找到mapper. xml文件中的SQL标签。(那么问题来了,如果两个不同的mapper.xml中有id相同的sql语句怎么办?对应到java就是两个不同的接口有同名的方法)。

还有一个习惯是: SQL映射文件(mapper. xml)和接口放在同一个包中(注意修改conf. xml中加载mapper. xml文件的路径)。

执行

先得到接口的实例化对象:

personMapper personMapper =sqlSession.getMapper(personMapper.class);

再通过接口的实例化对象来调用其方法(返回值自取):

int count=personMapper.addPerson(person);

最后增删改别忘了commit。

完整的方法如下:

public static void queryPersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

personMapper personMapper =sqlSession.getMapper(personMapper.class);
Person person=personMapper.queryPersonById(1);


System.out.println(person);
sqlSession.close();
reader.close();
}

public static void queryPersonByIdWithConverter() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

personMapper personMapper =sqlSession.getMapper(personMapper.class);
Person person=personMapper.queryPersonByIdWithConverter(1);


System.out.println(person);
sqlSession.close();
reader.close();
}


public static void queryAllPerson() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

personMapper personMapper =sqlSession.getMapper(personMapper.class);
List<Person> persons=personMapper.queryAll();

System.out.println(persons);
sqlSession.close();
reader.close();
}

public static void addPerson() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

Person person=new Person(19,"刘茜元",13);
personMapper personMapper =sqlSession.getMapper(personMapper.class);
int count=personMapper.addPerson(person);
sqlSession.commit();

System.out.println("增加了"+count+"个人");
sqlSession.close();
reader.close();
}

public static void addPersonWithConverter() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

Person person=new Person(19,"刘茜元",13);
personMapper personMapper =sqlSession.getMapper(personMapper.class);
int count=personMapper.addPersonWithConverter(person);
sqlSession.commit();

System.out.println("增加了"+count+"个人");
sqlSession.close();
reader.close();
}

public static void deletePersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

personMapper personMapper =sqlSession.getMapper(personMapper.class);
int count=personMapper.detelePersonById(13);
sqlSession.commit();

System.out.println("删除了"+count+"个人");
sqlSession.close();
reader.close();
}

public static void updatePersonById() throws IOException {
Reader reader=Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);//可以通过build的第二参数指定数据库环境
SqlSession sqlSession=sqlSessionFactory.openSession();

personMapper personMapper =sqlSession.getMapper(personMapper.class);
Person person=new Person();
person.setId(13);
person.setName("刘咯咯");
person.setAge(19);
int count=personMapper.updatePerson(person);
sqlSession.commit();

System.out.println("更新了"+count+"个人");
sqlSession.close();
reader.close();
}

发表评论