好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Mybatis新手教程之简单入门

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语句、结果映射配置),其对应着<select | update | delete | insert>标签项。

  2、sqlsessionfactorybuilder通过configuration对象生成sqlsessionfactory,用来开启sqlsession。

  3、sqlsession对象完成和数据库的交互:

  a、用户程序调用mybatis接口层api(即mapper接口中的方法)

  b、sqlsession通过调用api的statement id找到对应的mappedstatement对象

  c、通过executor(负责动态sql的生成和查询缓存的维护)将mappedstatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc statement对象

  d、jdbc执行sql。

  e、借助mappedstatement中的结果映射关系,将返回结果转化成hashmap、javabean等存储结构并返回。

下面是mybatis的框架原理图

  

3、mybatis简单实例

(1)导入相关jar包以及mybatis运行环境核心jar包和连接数据库的包

(2)创建一张简单的数据表

(3)创建java对象(po类型)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

package cn.mybatis.po;

 

public class user {

  private int id;

  private string username;

  private string password;

  private string address;

  private string sex;

 

  public int getid() {

  return id;

  }

 

  public string getusername() {

  return username;

  }

 

  public string getpassword() {

  return password;

  }

 

  public string getaddress() {

  return address;

  }

 

  public string getsex() {

  return sex;

  }

 

  public void setid( int id) {

  this .id = id;

  }

 

  public void setusername(string username) {

  this .username = username;

  }

 

  public void setpassword(string password) {

  this .password = password;

  }

 

  public void setaddress(string address) {

  this .address = address;

  }

 

  public void setsex(string sex) {

  this .sex = sex;

  }

 

  @override

  public string tostring() {

  return "user{" +

   "id=" + id +

   ", username='" + username + '\ '' +

   ", password='" + password + '\ '' +

   ", address='" + address + '\ '' +

   ", sex='" + sex + '\ '' +

   '}' ;

  }

}

 

user实体类

(4)创建mybatis核心配置文件(sqlmapconfig.xml)

在核心配置文件配置连接数据库的相关信息,(如果是和spring整合,则可以放在spring配置文件中进行对数据库的配置)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

<?xml version= "1.0" encoding= "utf-8" ?>

<!doctype configuration

  public "-//mybatis.org//dtd config 3.0//en"

  "http://mybatis.org/dtd/mybatis-3-config.dtd" >

<configuration>

  <!--加载资源文件-->

<!-- <properties resource= "jdbc.properties" ></properties>

  <!–settings配置log4j输出日志 –>

  <settings>

  <setting name= "logimpl" value= "log4j" />

  </settings>-->

  <!--typealiases配置包的别名-->

 

  <!--environments配置了数据库连接,配置了driver、url、username、password属性-->

  <environments default = "development" >

  <environment id= "development" >

   <transactionmanager type= "jdbc" >

   <!--<property name= "" value= "" />-->

   </transactionmanager>

   <datasource type= "pooled" >

   <property name= "driver" value= "com.mysql.jdbc.driver" />

   <property name= "url" value= "jdbc:mysql:///mybatis01" />

   <property name= "username" value= "root" />

   <property name= "password" value= "123" />

   </datasource>

  </environment>

  </environments>

  <!--配置一个sql语句和映射的配置文件-->

  <mappers>

  <mapper resource= "usermapper.xml" />

  </mappers>

</configuration>

 

mybatis核心配置文件

(5)创建一个mapper.xml文件,对应编写所需要的sql查询操作

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<?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" >

<!--mapper为根元素,namespace指定了命名空间-->

<mapper namespace= "test" >

  <!--定义一个select查询-->

  <!--parametertype:指定输入参数的类型-->

  <!--#{}表示占位符-->

  <!--#{id}:其中的id表示的就是接受的输入参数,

   参数名称就是id,

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

  <!--resulttype:指定输出类型(即指定输出结果所映射的java对象类型)-->

  <select id= "finduserbyid" parametertype= "int" resulttype= "cn.mybatis.po.user" >

  select * from t_user where id = #{id}

  </select>

</mapper>

 

usermapper配置文件

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

package cn.mybatis.first;

 

import cn.mybatis.po.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 java.io.ioexception;

import java.io.inputstream;

 

public class test {

 

  public user finduserbyid() throws ioexception {

  //得到mybatis配置文件

  string resource = "sqlmapconfig.xml" ;

  //得到配置文件的文件流信息

  inputstream inputstream = resources.getresourceasstream(resource);

  //创建会话工厂 传入mybatis的配置文件信息

  sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  //通过会话工厂得到sqlsession

  sqlsession sqlsession = sqlsessionfactory.opensession();

  //通过sqlsession来操作数据库

  //第一个参数就是映射文件中statment的id:namespace +statment的id

  //第二个参数就是制定映射文件中的parametertype类型的参数

  user user = sqlsession.selectone( "test.finduserbyid" , 1 );

  //system.out.println(user);

 

  //释放会话资源

 

  try {

   sqlsession.close();

  } catch (exception e) {

   e.printstacktrace();

  }

  return user;

  }

 

  public static void main(string[] args) {

  // todo auto-generated method stub

  test test = new test();

 

  try {

   system.out.println(test.finduserbyid());

  } catch (ioexception e) {

   e.printstacktrace();

  }

 

  }

}

 

test测试程序

(8)加入log4j日志文件

?

1

2

3

4

5

6

7

8

9

### direct log messages to stdout ###

 

log4j.rootlogger=debug, stdout

 

log4j.appender.stdout=org.apache.log4j.consoleappender

log4j.appender.stdout.layout=org.apache.log4j.patternlayout

log4j.appender.stdout.layout.conversionpattern=%5p [%t] - %m%n

 

log4j.properties

(9)测试结果

4.其他crud操作

(1)insert操作

在mapper文件中添加响应的sql配置,以及使用mysql中的last_insert_id()函数得到增加的数据的主键值

?

1

2

3

4

5

6

7

8

9

10

11

12

13

<insert id= "adduser" parametertype= "cn.mybatis.po.user" >

  <!--

  现在需要得到刚刚插入的记录中的主键值,只适用于自增主键的情况

  last_insert_id()

  keyproperty:将查询到的主键值设置到parametertype指定对象中的那个属性

  order:指定相对于insert的顺序

  resulttype:指定映射结果的结果类型

  -->

  <selectkey keyproperty= "id" order= "after" resulttype= "java.lang.integer" >

   select last_insert_id()

  </selectkey>

  insert into t_user(id,username,password,address,sex) values(#{id},#{username},#{password},#{address}, #{sex});

  </insert>

插入数据的日志信息,没有使用sqlsession测试数据mit();之前的日志情况

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

附上insertuser的函数

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public void inseruser() throws ioexception {

  //得到配置文件的文件流信息

  inputstream inputstream = resources.getresourceasstream( "sqlmapconfig.xml" );

  sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  sqlsession sqlsession = sqlsessionfactory.opensession();

 

  user user = new user( "world" , "1234" , "武汉市" , "男" );

  sqlsession.insert( "test.adduser" ,user);

  system.out.println(user.getid());

  sqlsession测试数据mit();

  //释放会话资源

  try {

   sqlsession.close();

  } catch (exception e) {

   e.printstacktrace();

  }

  }

 

inseruser函数

(2)模糊查询

首先配置mapper文件,${}和#{}的简单区别如下:

?

1

2

3

4

5

6

7

8

9

10

<!--

  模糊查询可能会查询多条记录

  resulttype:指定的就是查询结果对应的单条记录类型

  ${}:表示将输入的参数不加任何的修饰,直接作为字符串拼接在sql中

  但是这样直接拼接,容易导致sql注入的隐患

  ${value}中的value表示接受的输入参数,注意如果输入参数是简单类型,其中的形参只能用value

  -->

  <select id= "finduserbyusername" parametertype= "java.lang.string" resulttype= "cn.mybatis.po.user" >

  select * from t_user where username like '%${value}%'

  </select>

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

附上findbyusername的函数实现

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public void finduserbyusername() throws ioexception {

  //得到配置文件的文件流信息

  inputstream inputstream = resources.getresourceasstream( "sqlmapconfig.xml" );

  sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  sqlsession sqlsession = sqlsessionfactory.opensession();

 

  list<user> userlist = sqlsession.selectlist( "test.finduserbyusername" , "u" );

  system.out.println(userlist);

  //释放会话资源

  try {

   sqlsession.close();

  } catch (exception e) {

   e.printstacktrace();

  }

  }

 

findbyusername函数实现

(3)删除操作

首先在mapper中配置删除的操作

?

1

2

3

<delete id= "deleteuser" parametertype= "java.lang.integer" >

  delete from t_user where id = #{value}

</delete>

运行测试程序,同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)别名定义

     ①单个别名的定义

?

1

2

3

4

<typealiases>

  <!--针对单个别名的定义-->

  <typealias type= "cn.mybatis.po.user" alias= "user" ></typealias>

  </typealiases>

      定义别名后的使用

?

1

2

3

<select id= "finduserbyidtest" parametertype= "int" resulttype= "user" >

  select * from t_user where id = #{id}

</select>

     ②批量别名的定义

?

1

2

3

4

<typealiases>

  <!--批量别名定义:mybatis在定义别名的时候会自动扫描包中的po类,自动的将别名定义为类名(首字母大写或者小写都可以)-->

  < package name= "cn.mybatis.po" ></ package >

</typealiases>

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

  ①首先先注意一点:

     在配置mybatis-config.xml时,其中的节点是有顺序的,配置顺序依次为:

properties/settings/typealiases/typehandlers/objectfactory/objectwrapperfactory/plugins/environments/databaseidprovider/mappers

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

?

1

2

3

<mappers>

  <mapper class = "cn.mybatis.mapper.usermapper" ></mapper>

</mappers>

6.mybatis开发dao方法简介

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package cn.mybatis.dao;

 

import cn.mybatis.po.user;

 

/**

  * 原始dao方式开发:dao接口+dao实现类的方式

  */

public interface userdao {

 

  //根据id查询信息

  public user finduserbyid( int id) throws exception;

  //添加信息

  public void insertuser(user user) throws exception;

  //删除信息

  public void deleteuser( int id) throws exception;

}

 

dao接口

   b)然后编写接口实现

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

package cn.mybatis.dao.daoimpl;

 

import cn.mybatis.dao.userdao;

import cn.mybatis.po.user;

import org.apache.ibatis.session.sqlsession;

import org.apache.ibatis.session.sqlsessionfactory;

import org.junit.test;

 

public class userdaoimpl implements userdao {

 

  //使用构造方法注入sqlsessionfactory

  private sqlsessionfactory sqlsessionfactory;

 

  public userdaoimpl(sqlsessionfactory sqlsessionfactory) {

   this .sqlsessionfactory = sqlsessionfactory;

  }

 

  @override

  @test

  public user finduserbyid( int id) throws exception {

   sqlsession sqlsession = sqlsessionfactory.opensession();

 

   user user = sqlsession.selectone( "test.finduserbyid" ,id);

 

   sqlsession.close();

   return user;

  }

 

  @override

  public void insertuser(user user) throws exception {

   sqlsession sqlsession = sqlsessionfactory.opensession();

//  user user1 = new user("test1","123","洪山区","男");

   sqlsession.insert( "test.finduserbyid" ,user);

   sqlsession测试数据mit();

   sqlsession.close();

  }

 

  @override

  public void deleteuser( int id) throws exception {

   sqlsession sqlsession = sqlsessionfactory.opensession();

 

   sqlsession.delete( "test.finduserbyid" ,id);

   sqlsession测试数据mit();

   sqlsession.close();

  }

}

 

dao接口实现类

   c)mapper配置文件和sqlconfig配置文件不变

   d)使用junit进行测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

package cn.mybatis.testdao;

 

import cn.mybatis.dao.userdao;

import cn.mybatis.dao.daoimpl.userdaoimpl;

import cn.mybatis.po.user;

import org.apache.ibatis.io.resources;

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.inputstream;

 

public class userdaoimpltest {

 

  private sqlsessionfactory sqlsessionfactory;

 

  @before

  public void setup() throws exception {

   inputstream inputstream = resources.getresourceasstream( "sqlmapconfig.xml" );

   sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  }

 

  @test

  public void testfinduserbyid() throws exception{

   //创建userdao的对象

   userdao userdao = new userdaoimpl(sqlsessionfactory);

 

   //调用userdao的方法

   user user = userdao.finduserbyid( 1 );

 

   system.out.println(user );

  }

}

 

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配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<?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" >

<!--mapper为根元素,namespace指定了命名空间-->

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

<mapper namespace= "cn.mybatis.mapper.usermapper" >

  <select id= "finduserbyid" parametertype= "int" resulttype= "cn.mybatis.po.user" >

   select * from t_user where id = #{id}

  </select>

 

  <delete id= "deleteuser" parametertype= "java.lang.integer" >

   delete from t_user where id = #{value}

  </delete>

</mapper>

 

mapper.xml配置文件

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

package cn.mybatis.testmapper;

 

import cn.mybatis.mapper.usermapper;

import cn.mybatis.po.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.after;

import org.junit.before;

import org.junit.test;

 

import java.io.inputstream;

 

 

public class usermappertest {

 

  private sqlsessionfactory sqlsessionfactory;

 

  @before

  public void setup() throws exception {

   inputstream inputstream = resources.getresourceasstream( "sqlmapconfig.xml" );

   sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  }

 

  @test

  public void testfinduserbyid() throws exception{

 

   sqlsession sqlsession = sqlsessionfactory.opensession();

   //得到usermapper的代理对象

   usermapper usermapper = sqlsession.getmapper(usermapper. class );

 

   user user = usermapper.finduserbyid( 9 );

 

   system.out.println(user);

  }

 

  @test

  public void testdeleteuser() throws exception {

   sqlsession sqlsession = sqlsessionfactory.opensession();

   usermapper usermapper = sqlsession.getmapper(usermapper. class );

 

   usermapper.deleteuser( 9 );

   sqlsession测试数据mit();

  }

 

  @after

  public void teardown() throws exception {

  }

}

 

mapper接口

    ③junit测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

package cn.mybatis.testmapper;

 

import cn.mybatis.mapper.usermapper;

import cn.mybatis.po.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.after;

import org.junit.before;

import org.junit.test;

 

import java.io.inputstream;

 

 

public class usermappertest {

 

  private sqlsessionfactory sqlsessionfactory;

 

  @before

  public void setup() throws exception {

   inputstream inputstream = resources.getresourceasstream( "sqlmapconfig.xml" );

   sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);

  }

 

  @test

  public void testfinduserbyid() throws exception{

 

   sqlsession sqlsession = sqlsessionfactory.opensession();

   //得到usermapper的代理对象

   usermapper usermapper = sqlsession.getmapper(usermapper. class );

 

   user user = usermapper.finduserbyid( 8 );

 

   system.out.println(user);

  }

 

  @test

  public void testdeleteuser() throws exception {

   sqlsession sqlsession = sqlsessionfactory.opensession();

   usermapper usermapper = sqlsession.getmapper(usermapper. class );

 

   usermapper.deleteuser( 8 );

  }

 

  @after

  public void teardown() throws exception {

  }

}

 

junit测试

    ④查询结果展示

    ⑤删除结果展示

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

原文链接:https://HdhCmsTestcnblogs测试数据/fsmly/p/10324491.html

查看更多关于Mybatis新手教程之简单入门的详细内容...

  阅读:12次