Mybatis - 简单使用Mybatis 实现 增删改查

1.传统的JDBC实现

   首先我们先看下传统的JDBC的代码 :


public class JdbcDemo {

	private final static String CONN_URL="jdbc:oracle:thin:@localhost:1521:xe";
	private final static String ORACLE_DRIVER="oracle.jdbc.OracleDriver";
	private final static String CONN_NAME="hr";
	private final static String CONN_PASSWORD="hr";
	
	public static void main(String[] args) throws Exception {
		
		Class.forName(ORACLE_DRIVER);
		Connection conn = DriverManager.getConnection(CONN_URL, CONN_NAME, CONN_PASSWORD);
		String sql="select * from f_client";
		PreparedStatement psm = conn.prepareStatement(sql);
//		psm.setInt(1, 14);
		ResultSet rs = psm.executeQuery();
		while(rs.next()){
			 System.out.println(rs.getString("username")+" :"+rs.getString("now_address"));
		}
		rs.close();
		psm.close();
		conn.close();
	}
}

      在这里我们使用的是Oracle数据库,使用通过SQL语句操作数据库 ,会发现以下问题 :

    (1)数据库连接,使用时创建,不使用立即释放,对数据库频繁的连接开启和关闭,造成数据库资源浪费,影响数据库性能;
       解决:使用数据库连接池来解决;
  (2)将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护。
       解决:将sql语句配置在xml配置文件中,就不需要编译源代码了。
  (3)向preparedStatement中设置参数.对占位符位置和设置参数值,硬编码在java代码中,不利于维护;
       解决:将sql语句及占位符和参数全部配置在xml中;
  (4)从resutSet中遍历结果集数据时,存在硬编码,不利于维护;
       解决:将结果自动映射为java对象;


2.Mybatis的一些名词及其作用

   mybatis是持久层的框架,是apache下的顶级项目,可以github中clone;

   mybatis将主要精力放在sql上,通过mybatis提供的映射方式,自由的灵活生成(半自动化,大部分的程序需要的sql)满足的sql语句;
   mybatis可以将向preparedStatementa中输入参数自动进行输入映射,将查询结果集灵活的映射为java对象(输出映射);   
    
   SqlMapConfig.xml 是mybatis的全局配置文件,配置了数据源,事务等mybatis运行环境,配置映射文件(sql语句)mapper.xml...;
   
   SqlSessionFactory 会话工厂,作用:创建SqlSession;根据配置文件创建工厂
   
   SqlSession 会话 ,作用 :操作数据库,发出sql的增删改查;是接口
   
   Executor 执行器 ,作用 :sqlSession内部通过执行器操作数据库;是接口(基本执行器,缓存执行器)
   
   mapped statement 底层封装对象,作用 :对操作数据库存储封装,包括sql语句,输入参数,输出结果类型;
   
   数据输入输出的参数类型:值类型,hashmap ,pojo自定义。


3.实例 - 实现对客户信息的增删改查

        注意里面的所出现的名词,查看 2里面的相关名词 及其解释 ,mybatis实例代码在文章最后,包含里面的jar包均有(JDBC - Oracle数据库驱动)。

    (1)创建员工表和添加数据

           创建F_Client 客户表 :

CREATE TABLE F_CLIENT(
    ID NUMBER(12) PRIMARY KEY,--用户编号
    USERNAME VARCHAR2(20) NOT NULL,--用户姓名
    CLIENT_CERTIFICATE_NO VARCHAR2(20) NOT NULL UNIQUE,--证件号码
    BORN_DATE DATE,--出生日期
    FAMILY_REGISTER_ADDRESS VARCHAR2(200),--家庭住址
    NOW_ADDRESS VARCHAR2(200) NOT NULL,--现在住址
    CONTACT_MODE VARCHAR2(50) NOT NULL,--联系方式
    URGENCY_CONTACT_MODE VARCHAR2(50) NOT NULL,--紧急联系方式
    CREATE_DATE DATE NOT NULL--创建时间
);

         添加4条数据 :

     

insert into F_CLIENT (ID, USERNAME, CLIENT_CERTIFICATE_NO, BORN_DATE, FAMILY_REGISTER_ADDRESS, NOW_ADDRESS, CONTACT_MODE, URGENCY_CONTACT_MODE, CREATE_DATE)
values (1, 'sawyer', '1593224056', to_date('10-10-1980', 'dd-mm-yyyy'), '北京市海淀区东北旺', 'peaking', '123456789', '987654321', to_date('15-12-2015 08:47:13', 'dd-mm-yyyy hh24:mi:ss'));

insert into F_CLIENT (ID, USERNAME, CLIENT_CERTIFICATE_NO, BORN_DATE, FAMILY_REGISTER_ADDRESS, NOW_ADDRESS, CONTACT_MODE, URGENCY_CONTACT_MODE, CREATE_DATE)
values (2, 'yangly', '1593224057', to_date('11-10-1980', 'dd-mm-yyyy'), '北京市海淀区东北旺', 'peaking', '123456789', '987654321', to_date('15-12-2015 08:47:13', 'dd-mm-yyyy hh24:mi:ss'));

insert into F_CLIENT (ID, USERNAME, CLIENT_CERTIFICATE_NO, BORN_DATE, FAMILY_REGISTER_ADDRESS, NOW_ADDRESS, CONTACT_MODE, URGENCY_CONTACT_MODE, CREATE_DATE)
values (3, 'gaozhy', '1593224058', to_date('12-12-1980', 'dd-mm-yyyy'), '湖北省洪山区黄家湖', 'shanghai', '123456789', '987654321', to_date('15-12-2015 08:47:13', 'dd-mm-yyyy hh24:mi:ss'));

insert into F_CLIENT (ID, USERNAME, CLIENT_CERTIFICATE_NO, BORN_DATE, FAMILY_REGISTER_ADDRESS, NOW_ADDRESS, CONTACT_MODE, URGENCY_CONTACT_MODE, CREATE_DATE)
values (4, 'wangmj', '1593224059', to_date('13-04-1980', 'dd-mm-yyyy'), '湖北省洪山区黄家湖', 'hubei', '123456789', '987654321', to_date('15-12-2015 08:47:13', 'dd-mm-yyyy hh24:mi:ss'));

   (2)配置Log4j DEBUG

            新建Log4j.properties 文件

# Global logging configuration
# 开发的时候配置为 DEBUG 
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 

    (3)配置SqlMapConfig.xml

<?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>
        <!--临时配置的数据库访问数据-->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="oracle.jdbc.OracleDriver" />
				<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
				<property name="username" value="hr" />
				<property name="password" value="hr" />
			</dataSource>
		</environment>
	</environments>
        <!--配置mapper-->
	<mappers>
		<mapper resource="sqlmap/Client.xml" />
	</mappers>
</configuration>

  (4)实现客户表操作的mapper 

          1)注意namespace ,sql操作标签id,需要使用

          2)sql 语句不需要 分号 (;)

          3)parameterType 参数类型

          4)resultType 返回结果类型


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

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 -->
<!-- 注意:使用mapper代理的方法开发,namespace有特殊的重要作用 -->

<mapper namespace="test">

	<!-- 在映射文件中配置很多的sql语句 -->
	<!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id 
		#{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型 
		#{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 -->
	<!-- 根据id查用户 -->
	<select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">
		select * from f_client where id=#{id}
	</select>

	<!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入 
		${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 -->
	<select id="findClientByName" parameterType="java.lang.String"
		resultType="mybatis.po.FClient">
		select *from f_client where username like '%${value}%'
	</select>

	<!-- 添加用户 这里注意 主键返回实现 -->
	<select id="insertClient" parameterType="mybatis.po.FClient"
		resultType="java.lang.Integer">
		insert into
		f_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)
		values (#{id},
		#{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})
	</select>

	<!-- 删除用户 -->
	<delete id="deleteClient" parameterType="int">
		delete from f_client where id=#{id}
	</delete>

    <!-- 更新用户 -->
	<update id="updateClient" parameterType="mybatis.po.FClient">

		update f_client set
		username=#{username},client_certificate_no=#{client_certificate_no},born_date=#{born_date},family_register_address=#{family_register_address},now_address=#{now_address},contact_mode=#{contact_mode},urgency_contact_mode=#{urgency_contact_mode}
		where id=#{id}

	</update>


</mapper>




      命名: Client.xml(原始的) , mapper代理开发映射文件名称叫做xxxmapper.xml;
    作用: 在映射文件中配置sql语句
namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离;
注意:使用mapper代理的方法开发,namespace有特殊的重要作用;
paramterType : 在映射文件中通过指定参数类型
resultType :输出结果类型
#{} 表示一个占位符
${} 表示一个拼接符号,会引起sql注入,不建议使用;
selectOne 表示查询出一条记录进行映射
selectList 表示查询出一个列表(多条记录)进行映射


   (5)实现客户表的Pojo 

package mybatis.po;

import java.util.Date;


/**
 * 
 * 用户po
 * 作者:原明卓
 * 时间:2015年12月17日 下午2:58:18
 * 描述:TODO
 */
public class FClient {
	 @Override
	public String toString() {
		return "FClient [id=" + id + ", username=" + username
				+ ", client_certificate_no=" + client_certificate_no
				+ ", born_date=" + born_date + ", family_register_address="
				+ family_register_address + ", now_address=" + now_address
				+ ", contact_mode=" + contact_mode + ", urgency_contact_mode="
				+ urgency_contact_mode + ", create_data=" + create_data + "]";
	}
	//属性名和数据库名对应
	 private Integer id;
	 private String username;
	 private String client_certificate_no;
	 private Date born_date;
	 private String family_register_address;
	 private String now_address;
	 private String contact_mode;
	 private String urgency_contact_mode;
	 private Date create_data;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getClient_certificate_no() {
		return client_certificate_no;
	}
	public void setClient_certificate_no(String client_certificate_no) {
		this.client_certificate_no = client_certificate_no;
	}
	public Date getBorn_date() {
		return born_date;
	}
	public void setBorn_date(Date born_date) {
		this.born_date = born_date;
	}
	public String getFamily_register_address() {
		return family_register_address;
	}
	public void setFamily_register_address(String family_register_address) {
		this.family_register_address = family_register_address;
	}
	public String getNow_address() {
		return now_address;
	}
	public void setNow_address(String now_address) {
		this.now_address = now_address;
	}
	public String getContact_mode() {
		return contact_mode;
	}
	public void setContact_mode(String contact_mode) {
		this.contact_mode = contact_mode;
	}
	public String getUrgency_contact_mode() {
		return urgency_contact_mode;
	}
	public void setUrgency_contact_mode(String urgency_contact_mode) {
		this.urgency_contact_mode = urgency_contact_mode;
	}
	public Date getCreate_data() {
		return create_data;
	}
	public void setCreate_data(Date create_data) {
		this.create_data = create_data;
	}

}


  (6)实现操作方法

           1)使用Resources.getResourceAsStream(sqlmapconfig.xml) 加载数据库配置

           2)创建会话工厂 :参入为mybatis的配置文件信息

           3)通过工厂得到SqlSession

           4)通过sqkSession操作数据库 ,第一个参数:映射文件中statement的id等于=namespace+"."+statement的id,结果与ResultType 的结果集一样

           5)释放资源


package mybatis.frist;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

import mybatis.po.FClient;

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

/**
 * 测试Mybatis
 *
 * 作者:原明卓 时间:2015年12月17日 下午4:37:25 描述:TODO
 */
public class TestMyBatis {

	// 根据id查询用户信息,得到一条记录结果
	@Test
	public void findClientByIdTest() {
		String resource = "SqlMapConfig.xml";

		InputStream is;
		SqlSession os = null;
		try {
			is = Resources.getResourceAsStream(resource);
			// 创建会话工厂 :参入为mybatis的配置文件信息
			SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);

			// 通过工厂得到SqlSession
			os = build.openSession();

			// 通过sqkSession操作数据库
			// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id
			// 结果与ResultType 的结果集一样
			FClient client = os.selectOne("test.findClientById", 14);

			System.out.println(client);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 释放资源
				os.close();
			}
		}
	}

	/**
	 * 根据用户姓名模糊查询
	 */
	@Test
	public void findClientByNameTest() {
		String resource = "SqlMapConfig.xml";

		InputStream is;
		SqlSession os = null;
		try {
			is = Resources.getResourceAsStream(resource);
			// 创建会话工厂 :参入为mybatis的配置文件信息
			SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);

			// 通过工厂得到SqlSession
			os = build.openSession();

			// 通过sqkSession操作数据库
			// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id
			// 结果与ResultType 的结果集一样
			List<FClient> clients = os
					.selectList("test.findClientByName", "ya");

			System.out.println(clients);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 释放资源
				os.close();
			}
		}
	}

	/**
	 * 添加用户信息
	 */
	@Test
	public void addClient() {
		String resource = "SqlMapConfig.xml";

		InputStream is;
		SqlSession os = null;
		try {
			is = Resources.getResourceAsStream(resource);
			// 创建会话工厂 :参入为mybatis的配置文件信息
			SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);

			// 通过工厂得到SqlSession
			os = build.openSession();

			// 通过sqkSession操作数据库
			// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id
			// 结果与ResultType 的结果集一样
			FClient c = new FClient();
			c.setId(5);
			c.setBorn_date(new Date());
			c.setClient_certificate_no("我是新增的");
			c.setContact_mode("我是新增的");
			c.setCreate_data(new Date());
			c.setFamily_register_address("我是新增的");
			c.setNow_address("我是新增的");
			c.setUrgency_contact_mode("我是新增的");
			c.setUsername("yuha");

			int row = os.insert("test.insertClient", c);
			System.out.println(row);
			// 提交事务
			os.commit();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 释放资源
				os.close();
			}
		}

	}
	
	@Test
	public void deleteClient() {
		String resource = "SqlMapConfig.xml";

		InputStream is;
		SqlSession os = null;
		try {
			is = Resources.getResourceAsStream(resource);
			// 创建会话工厂 :参入为mybatis的配置文件信息
			SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);

			// 通过工厂得到SqlSession
			os = build.openSession();

			// 通过sqkSession操作数据库
			// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id
			// 结果与ResultType 的结果集一样

			os.delete("test.deleteClient",15);
			os.commit();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 释放资源
				os.close();
			}
		}

	}
	
	
	@Test
	public void updateClient() {
		String resource = "SqlMapConfig.xml";

		InputStream is;
		SqlSession os = null;
		try {
			is = Resources.getResourceAsStream(resource);
			// 创建会话工厂 :参入为mybatis的配置文件信息
			SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);

			// 通过工厂得到SqlSession
			os = build.openSession();

			// 通过sqkSession操作数据库
			// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id
			// 结果与ResultType 的结果集一样

			FClient c = new FClient();
			c.setId(4);
			c.setBorn_date(new Date());
			c.setClient_certificate_no("我是修改的1");
			c.setContact_mode("我是修改的");
			c.setCreate_data(new Date());
			c.setFamily_register_address("我是修改增的");
			c.setNow_address("我是修改的");
			c.setUrgency_contact_mode("我是修改的");
			c.setUsername("yuha");
			
			os.update("test.updateClient", c);
			// 提交事务
			os.commit();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 释放资源
				os.close();
			}
		}

	}

}

    (6)实现主键返回 

             在client.xml 的mapper中实现 :

    主键返回 : 
		   mysql: 自增主键返回 使用函数 LAST_INSERT_ID() ,相对于insert语句,在其后执行
		     <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Intger">
                 <!--
                                          插入数据,返回主键id. 返回到keyProperty(为 parameterType的某个属性里)
            order :执行的顺序,相对于insert 语句来说的执行顺序
                  -->
                 Select LAST_INSERT_ID()
             </selectKey>
		           非自增主键,使用uuid()函数生成主键,相对于insert语句,在其后执行
			 <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Intger">
                <!--
                                          插入数据,返回主键id. 返回到keyProperty(为 parameterType的某个属性里)
                     order :执行的顺序,相对于insert 语句来说的执行顺序
                        -->
                 Select UUID()
              </selectKey>
			  
			  Oracel : 使用序列实现,和mysql非自增主键相似;



4.mybatis和hibernate 本质区别和应用场景

 ( 1)hibernate 是一个标准的ORM(对象关系映射)框架,入门门槛高,不需要写sql,sql自动生成,对sql语句进行优化,修改比较困难;
     应用场景 : 适应与需求变化不多的中小型项目,比如:后台管理系统;
  
 ( 2)mybatis 专注的是sql本身,需要自己编写sql语句,sql修改,优化比较方便,一个不完全的orm框架,虽然自己写sql , 也可以实现映射(输入输出映射);
     应用场景 :适应与需求变化较多的项目,比如 :互联网项目;

5.Demo 免积分下载

http://download.csdn.net/detail/lablenet/9369787


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值