飞奔的炮台 发表于 2021-9-18 19:19:59

Mybatis新手教程之简单入门

这篇文章主要给大家介绍了关于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类型)


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配置文件中进行对数据库的配置)


<?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查询操作


<?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查询进行测试


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日志文件


### 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()函数得到增加的数据的主键值


<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.commit();之前的日志情况

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

附上insertuser的函数


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.commit();
//释放会话资源
try {
sqlsession.close();
} catch (exception e) {
e.printstacktrace();
}
}

inseruser函数
(2)模糊查询
首先配置mapper文件,${}和#{}的简单区别如下:


<!--
模糊查询可能会查询多条记录
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的函数实现


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中配置删除的操作


<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)别名定义
①单个别名的定义


<typealiases>
<!--针对单个别名的定义-->
<typealias type="cn.mybatis.po.user" alias="user"></typealias>
</typealiases>
定义别名后的使用


<select id="finduserbyidtest" parametertype="int" resulttype="user">
select * from t_user where id = #{id}
</select>
②批量别名的定义


<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代理的方式进行开发


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

6.mybatis开发dao方法简介
(1)使用dao接口+实现类的方式
a)首先编写接口,如同一般编写模式方式进行编写


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)然后编写接口实现


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.commit();
sqlsession.close();
}

@override
public void deleteuser(int id) throws exception {
sqlsession sqlsession = sqlsessionfactory.opensession();

sqlsession.delete("test.finduserbyid",id);
sqlsession.commit();
sqlsession.close();
}
}

dao接口实现类
c)mapper配置文件和sqlconfig配置文件不变
d)使用junit进行测试


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


<?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的接口


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.commit();
}

@after
public void teardown() throws exception {
}
}

mapper接口
③junit测试


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测试
④查询结果展示

⑤删除结果展示

总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对CodeAE代码之家的支持。
原文链接:https://www.cnblogs.com/fsmly/p/10324491.html

http://www.zzvips.com/article/176511.html
页: [1]
查看完整版本: Mybatis新手教程之简单入门