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

来源:互联网 发布:我的世界ae2处理子网络 编辑:程序博客网 时间:2024/06/07 05:36

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.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 

    (3)配置SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//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 mapperPUBLIC "-//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 intof_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 setusername=#{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 { @Overridepublic 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查询用户信息,得到一条记录结果@Testpublic void findClientByIdTest() {String resource = "SqlMapConfig.xml";InputStream is;SqlSession os = null;try {is = Resources.getResourceAsStream(resource);// 创建会话工厂 :参入为mybatis的配置文件信息SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);// 通过工厂得到SqlSessionos = 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 blocke.printStackTrace();} finally {if (os != null) {// 释放资源os.close();}}}/** * 根据用户姓名模糊查询 */@Testpublic void findClientByNameTest() {String resource = "SqlMapConfig.xml";InputStream is;SqlSession os = null;try {is = Resources.getResourceAsStream(resource);// 创建会话工厂 :参入为mybatis的配置文件信息SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);// 通过工厂得到SqlSessionos = 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 blocke.printStackTrace();} finally {if (os != null) {// 释放资源os.close();}}}/** * 添加用户信息 */@Testpublic void addClient() {String resource = "SqlMapConfig.xml";InputStream is;SqlSession os = null;try {is = Resources.getResourceAsStream(resource);// 创建会话工厂 :参入为mybatis的配置文件信息SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);// 通过工厂得到SqlSessionos = 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 blocke.printStackTrace();} finally {if (os != null) {// 释放资源os.close();}}}@Testpublic void deleteClient() {String resource = "SqlMapConfig.xml";InputStream is;SqlSession os = null;try {is = Resources.getResourceAsStream(resource);// 创建会话工厂 :参入为mybatis的配置文件信息SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);// 通过工厂得到SqlSessionos = build.openSession();// 通过sqkSession操作数据库// 第一个参数:映射文件中statement的id等于=namespace+"."+statement的id// 结果与ResultType 的结果集一样os.delete("test.deleteClient",15);os.commit();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (os != null) {// 释放资源os.close();}}}@Testpublic void updateClient() {String resource = "SqlMapConfig.xml";InputStream is;SqlSession os = null;try {is = Resources.getResourceAsStream(resource);// 创建会话工厂 :参入为mybatis的配置文件信息SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);// 通过工厂得到SqlSessionos = 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 blocke.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


0 0
原创粉丝点击