Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Mybatis简单入门

风沙迷了眼 2019-02-04 06:51:00 阅读数:197 评论数:0 点赞数:0 收藏数:0

 

1、Mybatis概述

MyBatis 是支持普通 SQL 查询(相比较于Hibernate的封装,Mybatis是半自动化的JDBC封装,一个特点就是Mybatis执行的SQL查询语句需要自己在配置文件中写),存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索。MyBatis 可以使用简单的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的Java 对象)映射成数据库中的记录。

2、Mybatis原理解析

下面以Mybatis简单的执行流程

1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着 17 UserMapper配置文件

  (7)创建测试程序,对刚刚编写的select查询进行测试

1 packagecn.mybatis.first;2 3 importcn.mybatis.po.User;4 importorg.apache.ibatis.io.Resources;5 importorg.apache.ibatis.session.SqlSession;6 importorg.apache.ibatis.session.SqlSessionFactory;7 importorg.apache.ibatis.session.SqlSessionFactoryBuilder;8 9 importjava.io.IOException;10 importjava.io.InputStream;11 12 public classTest {13 14 public User findUserById() throwsIOException {15 //得到mybatis配置文件 16 String resource = "SqlMapConfig.xml";17 //得到配置文件的文件流信息 18 InputStream inputStream =Resources.getResourceAsStream(resource);19 //创建会话工厂 传入mybatis的配置文件信息 20 SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);21 //通过会话工厂得到SqlSession 22 SqlSession sqlSession =sqlSessionFactory.openSession();23 //通过sqlSession来操作数据库24 //第一个参数就是映射文件中statment的id:namespace +statment的id25 //第二个参数就是制定映射文件中的parameterType类型的参数 26 User user = sqlSession.selectOne("test.findUserById",1);27 //System.out.println(user);28 29 //释放会话资源 30 31 try{32 sqlSession.close();33 } catch(Exception e) {34 e.printStackTrace();35 }36 returnuser;37 }38 39 public static voidmain(String[] args) {40 //TODO Auto-generated method stub 41 Test test = newTest();42 43 try{44 System.out.println(test.findUserById());45 } catch(IOException e) {46 e.printStackTrace();47 }48 49 }50 }Test测试程序

  (8)加入Log4j日志文件

1 /#/#/# direct log messages to stdout /#/#/#2 3 log4j.rootLogger=DEBUG, stdout4 5 log4j.appender.stdout=org.apache.log4j.ConsoleAppender6 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout7 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%nLog4j.properties  

  (9)测试结果

 4.其他CRUD操作

(1)insert操作

在Mapper文件中添加响应的SQL配置,以及使用MySQL中的LASTINSERTID()函数得到增加的数据的主键值 SELECT LASTINSERTID()INSERT INTO t_user(id,username,password,address,sex) VALUES(/#{id},/#{username},/#{password},/#{address}, /#{sex});

插入数据的日志信息,没有使用sqlSession.commit();之前的日志情况

从上面的图中可以看出,没有添加commit的时候,事务进行了回滚,所以要想添加数据,需要自己手动提交(在没有整合Spring之前)

附上insertUser的函数

1 public void inserUser() throwsIOException {2 //得到配置文件的文件流信息 3 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");4 SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);5 SqlSession sqlSession =sqlSessionFactory.openSession();6 7 User user = new User("World","1234","武汉市","男");8 sqlSession.insert("test.addUser",user);9 System.out.println(user.getId());10 sqlSession.commit();11 //释放会话资源 12 try{13 sqlSession.close();14 } catch(Exception e) {15 e.printStackTrace();16 }17 }inserUser函数

(2)模糊查询

首先配置Mapper文件,${}和/#{}的简单区别如下:1 8 9 SELECT /* FROM t_user WHERE username LIKE '%${value}%'10

使用查询的时候碰到一个小错误,由于之前测试的insert方法,其中在User实体类中添加了有参构造函数,所以出现了下面的错误,分析原因就是:使用Mybatis查询的时候需要在实体类中加入无参构造方法(当然如果实体类本身没有构造函数,就会是默认的无参构造函数)

 

  附上findByUsername的函数实现

1 public void findUserByUsername() throwsIOException {2 //得到配置文件的文件流信息 3 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");4 SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);5 SqlSession sqlSession =sqlSessionFactory.openSession();6 7 List userList = sqlSession.selectList("test.findUserByUsername","u");8 System.out.println(userList);9 //释放会话资源 10 try{11 sqlSession.close();12 } catch(Exception e) {13 e.printStackTrace();14 }15 }findByUsername函数实现

  (3)删除操作

首先在Mapper中配置删除的操作1 2 DELETE FROM t_user WHERE id = /#{value}3

运行测试程序,同insert中一样,需要手动提交事务,如下面所示

最终结果:

数据表中删除了编号为10的数据记录

5.细节整理

(1)关于示例程序中一些相关类的理解

a)SqlSessionFactoryBuilder

用来创建SqlSessionFactory。因为SqlSessionFactory使用了单例模式,所以不需要使用单例模式来管理SqlSessionFactoryBuilder,只需要在创建SqlSessionFactory时 候使用一次就可以

b)SqlSessionFactory

会话工厂,用来创建SqlSession。可以使用单例模式来管理SqlSessionFactory这个会话工厂,工厂创建之后,就一直使用一个实例。

c)SqlSession

面向程序员的接口,提供了操作数据库的方法。SqlSession是线程不安全的(原因:在SqlSession实现类中除了接口中的操作数据库的方法之外,还有数据域的属性,比如说一些提交的数据等等,所以在多线程并发请求的时候,会导致线程不安全),所以我们可以将SqlSession使用在方法体里面,这样每个线程都有自己的方法,就不会冲突

(2)Mybatis中mapper映射文件

如同解释Mybatis执行原理的时候一样,Mapper映射文件中配置的Sql语句,实际上在执行的时候都被封装称为一个个MapperStatment对象,即Mapper映射文件是按照statment来管理不同的Sql。在编写程序的时候,我们在使用SqlSession其中的操作数据库的方法(selectOne,selectList等等)的时候,传入的参数除了实参(id,模糊查询的字符串等等)之外,还需要传入的就是相应的Sql位置,而Sql是被Statment管理,所以就是传入namespace+statmentId

(3)占位符

/#{id}:其中的id表示的就是接受的输入参数,参数名称就是id,这里指出:如果输入参数是简单类型,/#{}中的参数名可以任意设置(value或者其他名称)

${value}:表示将输入的参数不加任何的修饰,直接作为字符串拼接在SQL中但是这样直接拼接,容易导致SQL注入的隐患${value}中的value表示接受的输入参数,注意如果输入参数是简单类型,其中的形参只能用value

**(4)别名定义**

  ①单个别名的定义

  定义别名后的使用

SELECT /* FROM t_user WHERE id = /#{id}

  ②批量别名的定义

(5)在SqlMapConfig.xml中加载Mapper映射文件的时候,除了通过resource的方式,还可以使用mapper接口加载的方式来实现

  ①首先先注意一点:

  在配置mybatis-config.xml时,其中的节点是有顺序的,配置顺序依次为:properties/settings/typeAliases/typeHandlers/objectFactory/objectWrapperFactory/plugins/environments/databaseIdProvider/mappers

  ②使用mapper加载的方式,要将mapper接口和mapper配置文件放在同一目录下面,并且文件名称一致,而且要遵循mapper代理的方式进行开发

  

 

6.Mybatis开发dao方法简介

(1)使用dao接口+实现类的方式

a)首先编写接口,如同一般编写模式方式进行编写

1 packagecn.mybatis.dao;2 3 importcn.mybatis.po.User;4 5 /// 6 / 原始Dao方式开发:dao接口+dao实现类的方式7 // 8 public interfaceUserDao {9 10 //根据id查询信息 11 public User findUserById(int id) throwsException;12 //添加信息 13 public void insertUser(User user) throwsException;14 //删除信息 15 public void deleteUser(int id) throwsException;16 }dao接口

b)然后编写接口实现

1 packagecn.mybatis.dao.daoImpl;2 3 importcn.mybatis.dao.UserDao;4 importcn.mybatis.po.User;5 importorg.apache.ibatis.session.SqlSession;6 importorg.apache.ibatis.session.SqlSessionFactory;7 importorg.junit.Test;8 9 public class UserDaoImpl implementsUserDao {10 11 //使用构造方法注入SqlSessionFactory 12 privateSqlSessionFactory sqlSessionFactory;13 14 publicUserDaoImpl(SqlSessionFactory sqlSessionFactory) {15 this.sqlSessionFactory =sqlSessionFactory;16 }17 18 @Override19 @Test20 public User findUserById(int id) throwsException {21 SqlSession sqlSession =sqlSessionFactory.openSession();22 23 User user = sqlSession.selectOne("test.findUserById",id);24 25 sqlSession.close();26 returnuser;27 }28 29 @Override30 public void insertUser(User user) throwsException {31 SqlSession sqlSession =sqlSessionFactory.openSession();32 //User user1 = new User("test1","123","洪山区","男"); 33 sqlSession.insert("test.findUserById",user);34 sqlSession.commit();35 sqlSession.close();36 }37 38 @Override39 public void deleteUser(int id) throwsException {40 SqlSession sqlSession =sqlSessionFactory.openSession();41 42 sqlSession.delete("test.findUserById",id);43 sqlSession.commit();44 sqlSession.close();45 }46 }dao接口实现类

c)Mapper配置文件和SqlConfig配置文件不变

d)使用Junit进行测试

1 packagecn.mybatis.testdao;2 3 importcn.mybatis.dao.UserDao;4 importcn.mybatis.dao.daoImpl.UserDaoImpl;5 importcn.mybatis.po.User;6 importorg.apache.ibatis.io.Resources;7 importorg.apache.ibatis.session.SqlSessionFactory;8 importorg.apache.ibatis.session.SqlSessionFactoryBuilder;9 importorg.junit.After;10 importorg.junit.Before;11 importorg.junit.Test;12 13 importjava.io.InputStream;14 15 public classUserDaoImplTest {16 17 privateSqlSessionFactory sqlSessionFactory;18 19 @Before20 public void setUp() throwsException {21 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");22 sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);23 }24 25 @Test26 public void testFindUserById() throwsException{27 //创建UserDao的对象 28 UserDao userDao = newUserDaoImpl(sqlSessionFactory);29 30 //调用UserDao的方法 31 User user = userDao.findUserById(1);32 33 System.out.println(user );34 }35 }Junit测试

     e)测试结果

f)原始dao方法的问题

①dao接口实现中存在大量的模板方法(即很多重复性的代码 )

②调用SqlSession方法的时候将statmentid硬编码了

③条用SqlSession方法的时候传入的参数,由于使用泛型,所以在编译阶段不会报错(即使传入参数错误)

(2)使用Mapper代理的方法(即只需要Mapper接口)

(a)使用mapper方式的规范

①在使用mapper代理的方式中,namespace的值应该是mapper接口的路径

②在mapper.java接口文件中的接口方法名称和mapper.xml中的statment的id一致

③在mapper.java接口文件中的接口方法的输入参数和mapper.xml中的statment的parameterType一致

④在mapper.java接口文件中的接口方法的返回值类型和mapper.xml中的statment的resultType一致

(b)查询、删除操作实例

①编写mapper.xml配置文件,其中包含select和delete的sql配置

SELECT /* FROM t_user WHERE id = /#{id} DELETE FROM t_user WHERE id = /#{value} mapper.xml配置文件

②编写mapper接口,按照mapper代理的方式开发规范来编写mapper的接口

1 packagecn.mybatis.testmapper;2 3 importcn.mybatis.mapper.UserMapper;4 importcn.mybatis.po.User;5 importorg.apache.ibatis.io.Resources;6 importorg.apache.ibatis.session.SqlSession;7 importorg.apache.ibatis.session.SqlSessionFactory;8 importorg.apache.ibatis.session.SqlSessionFactoryBuilder;9 importorg.junit.After;10 importorg.junit.Before;11 importorg.junit.Test;12 13 importjava.io.InputStream;14 15 16 public classUserMapperTest {17 18 privateSqlSessionFactory sqlSessionFactory;19 20 @Before21 public void setUp() throwsException {22 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");23 sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);24 }25 26 @Test27 public void testFindUserById() throwsException{28 29 SqlSession sqlSession =sqlSessionFactory.openSession();30 //得到UserMapper的代理对象 31 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);32 33 User user = userMapper.findUserById(9);34 35 System.out.println(user);36 }37 38 @Test39 public void testDeleteUser() throwsException {40 SqlSession sqlSession =sqlSessionFactory.openSession();41 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);42 43 userMapper.deleteUser(9);44 sqlSession.commit();45 }46 47 @After48 public void tearDown() throwsException {49 }50 }mapper接口

③Junit测试

1 packagecn.mybatis.testmapper;2 3 importcn.mybatis.mapper.UserMapper;4 importcn.mybatis.po.User;5 importorg.apache.ibatis.io.Resources;6 importorg.apache.ibatis.session.SqlSession;7 importorg.apache.ibatis.session.SqlSessionFactory;8 importorg.apache.ibatis.session.SqlSessionFactoryBuilder;9 importorg.junit.After;10 importorg.junit.Before;11 importorg.junit.Test;12 13 importjava.io.InputStream;14 15 16 public classUserMapperTest {17 18 privateSqlSessionFactory sqlSessionFactory;19 20 @Before21 public void setUp() throwsException {22 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");23 sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);24 }25 26 @Test27 public void testFindUserById() throwsException{28 29 SqlSession sqlSession =sqlSessionFactory.openSession();30 //得到UserMapper的代理对象 31 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);32 33 User user = userMapper.findUserById(8);34 35 System.out.println(user);36 }37 38 @Test39 public void testDeleteUser() throwsException {40 SqlSession sqlSession =sqlSessionFactory.openSession();41 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);42 43 userMapper.deleteUser(8);44 }45 46 @After47 public void tearDown() throwsException {48 }49 }Junit测试

④查询结果展示

⑤删除结果展示

 

版权声明
本文为[风沙迷了眼]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/fsmly/p/10324491.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领