MyBatis3入门三(增加、删除、修改、查询,自增长,允许空值,封装Mapper)

1. 环境

mybatis-3.2版本,jdk1.6版本,Oracle数据库

2. 功能

1). 实现实体的增加、删除、修改、查询等基本功能,查询包括返回多条记录的;

2). 数据库为Oracle,插入时要求实现自增长主键的功能(从SEQUENCE中取值),同时要求插入后能够查询到新加的实体的主键值;

3). 如果数据库中表结构设计某些字段允许为空值,那么在MyBatis中配置它允许为空,简化程序调用;

4). 实现Mapper接口,封装SqlSession之类的调用,进一步简化程序的调用,就像操作普通对象一样,感觉不到后台数据库。

3. 环境准备

3.1 下载mybatis-3.2,需要引用其中的若干包

参考:MyBatis3入门级示范一(查询,插入)

3.2 项目的目录结构

src\com\clzhang\sample\struts2\mapper           
  ProductMapper.java                 mybatis的mapper接口类
src\com\clzhang\sample\struts2\mapper\entity    
  ProductBean.java                   mybatis的entity类
src\com\clzhang\sample\struts2\mapper\impl           
  ProductMapperImpl.java               mybatis的mapper接口实现类
src\com\clzhang\sample\struts2\util   MyBatisSessionFactory.java            SqlSessionFactory的能用获取类
src\com\clzhang\sample\struts2\test            
  MyBatisTest2.java                 测试类,最终应该是在service的package中调用mapper中的方法。 resources\config   mybatis
-config.xml mybatis的配置文件   jdbc.properties       JDBC连接配置文件 resources\com\clzhang\sample\struts2\mapper   ProductMapper.xml mybatis的mapper配置文件

3.3 假定数据库已经创建,表结构也已经创建,并且有测试数据

这里数据库为Oracle,表名为:PRODUCT,序列名:SEQ_PRODUCT,表结构如下(假设已经存在测试数据):

CREATE TABLE PRODUCT(
  PRODID NUMBER(38) NOT NULL PRIMARY KEY,
  PRODSERIAL VARCHAR2(20),
  PRODNAME VARCHAR2(50) NOT NULL,
  CATEGORYNAME VARCHAR2(20),
  PRODSPEC VARCHAR2(50),
  PRODPRICE NUMBER(12,2),
  PRODDESC VARCHAR2(1024),
  PRODIMAGE VARCHAR2(150),
  ISNEW NUMBER(38) NOT NULL,
  ISRECOMMEND NUMBER(38) NOT NULL,
  ISSHOW NUMBER(38) NOT NULL,
  USERNAME VARCHAR2(20)NOT NULL,
  HANDLETIME DATE,
  RODTHUMBNAIL VARCHAR2(150));

CREATE SEQUENCE SEQ_PRODUCT;

4. 具体步骤

4.1 创建entity类

package com.clzhang.sample.struts2.mapper.entity;

import java.sql.Timestamp;

/**
 * 数据库实体类,可以借助工具自动生成此类;
 * 也可以自己写一个程序从数据库读取数据,然后生成此类。
 * @author acer
 *
 */
public class ProductBean {
    
    private int prodId;
    private String prodSerial;
    private String prodName;
    private String categoryname;
    private String prodSpec;
    private double prodPrice;
    private String prodDesc;
    private String prodImage;
    private int isNew;
    private int isRecommend;
    private int isShow;
    private String username;
    private Timestamp handletime;
    private String prodThumbnail;

      public int getProdId() {
        return prodId;
    }


    public void setProdId(int prodId) {
        this.prodId = prodId;
    }


    public String getProdSerial() {
        return prodSerial;
    }


    public void setProdSerial(String prodSerial) {
        this.prodSerial = prodSerial;
    }


    public String getProdName() {
        return prodName;
    }


    public void setProdName(String prodName) {
        this.prodName = prodName;
    }


    public String getCategoryname() {
        return categoryname;
    }


    public void setCategoryname(String categoryname) {
        this.categoryname = categoryname;
    }


    public String getProdSpec() {
        return prodSpec;
    }


    public void setProdSpec(String prodSpec) {
        this.prodSpec = prodSpec;
    }


    public double getProdPrice() {
        return prodPrice;
    }


    public void setProdPrice(double prodPrice) {
        this.prodPrice = prodPrice;
    }


    public String getProdDesc() {
        return prodDesc;
    }


    public void setProdDesc(String prodDesc) {
        this.prodDesc = prodDesc;
    }


    public String getProdImage() {
        return prodImage;
    }


    public void setProdImage(String prodImage) {
        this.prodImage = prodImage;
    }


    public int getIsNew() {
        return isNew;
    }


    public void setIsNew(int isNew) {
        this.isNew = isNew;
    }


    public int getIsRecommend() {
        return isRecommend;
    }


    public void setIsRecommend(int isRecommend) {
        this.isRecommend = isRecommend;
    }


    public int getIsShow() {
        return isShow;
    }


    public void setIsShow(int isShow) {
        this.isShow = isShow;
    }


    public String getUsername() {
        return username;
    }


    public void setUsername(String username) {
        this.username = username;
    }


    public Timestamp getHandletime() {
        return handletime;
    }


    public void setHandletime(Timestamp handletime) {
        this.handletime = handletime;
    }


    public String getProdThumbnail() {
        return prodThumbnail;
    }


    public void setProdThumbnail(String prodThumbnail) {
        this.prodThumbnail = prodThumbnail;
    }

}

4.2 创建mapper接口类

package com.clzhang.sample.struts2.mapper;

import java.util.*;

import com.clzhang.sample.struts2.mapper.entity.ProductBean;

/**
 * 一个简单的CRUD操作示范类,接口,具体由impl包中的实现类实现具体功能。
 * @author Administrator
 *
 */
public interface ProductMapper {
    public void insertProduct(ProductBean product);    
    public void updateProduct(ProductBean product);    
    public void deleteProduct(int prodId); 
    
    public ProductBean getProduct(int prodId); 
    public List<ProductBean> getProdByCategory(String categoryName); 
}

4.3 创建jdbc.properties文件,位置于resources/config目录

#main database settings
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.2.136:1521:jingdu
jdbc.username=jingdu
jdbc.password=jingdu

4.4 创建mybatis-config.xml配置文件,位置于resources/config目录

<?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="config/jdbc.properties">
        <!--username 和 password 将会由 properties 元素中设置的值来替换-->
        <property name="username" value="mytest"/>
        <property name="password" value="yourpass"/>
    </properties>    
    <settings>
        <!--这些是极其重要的调整, 它们会修改 MyBatis 在运行时的行为方式。-->
        <setting name="cacheEnabled" value="false"/>
        <setting name="useGeneratedKeys" value="false"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <setting name="jdbcTypeForNull" value="OTHER"/>
    </settings>
    <typeAliases> 
       <!--
        类型别名是为 Java 类型命名一个短的名字。它只和 XML 配置有关, 只用来减少类完全限定名的多余部分。
        You can also specify a package where MyBatis will search for beans. For example
        <typeAliases>
            <package name="domain.blog"/>
        </typeAliases>
        ......
       -->
       <typeAlias alias="Product" type="com.clzhang.sample.struts2.mapper.entity.ProductBean"/> 
    </typeAliases> 
    <environments default="development"> 
       <environment id="development"> 
           <transactionManager type="JDBC"/> 
           <!--
           在 MyBatis 中有两种事务管理器类型(也就是 type=”[JDBC|MANAGED]”)
            <transactionManager type="MANAGED">
                <property name="closeConnection" value="false"/>
            </transactionManager>
            NOTE If you are planning to use MyBatis with Spring there is no need to configure any TransactionManager because the Spring module will set its own one overriding any previously set configuration. 
           -->
           <dataSource type="POOLED"> 
              <property name="driver" value="${jdbc.driver}"/> 
              <property name="url" value="${jdbc.url}"/> 
              <property name="username" value="${jdbc.username}"/> 
              <property name="password" value="${jdbc.password}"/> 
              <!--
              <property name="poolMaximumActiveConnections " value="10"/> 
              ......
              -->
           </dataSource> 
       </environment> 
    </environments> 
    <mappers> 
        <mapper resource="com/clzhang/sample/struts2/mapper/ProductMapper.xml" />
        <!--其它装载方式
        <mapper url="file:///var/mappers/AuthorMapper.xml"/>
        <mapper class="org.mybatis.builder.BlogMapper"/>
        -->
    </mappers> 
</configuration>

4.5 创建ProductMapper.xml配置文件,位置于:resources\com\clzhang\sample\struts2\mapper\

<?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的值设置得非常短,主要是考虑到项目不大的情况下,使用上的方便。比如在Java代码如下调用即可:
session.insert("ProductMapper.insertProduct", product);
如果项目非常大的话,那么还是建议使用长文件名做标识。
-->
<mapper namespace="ProductMapper">
    <!--
    默认情况下是没有开启缓存的,下条代码是开启二级缓存的,作用如下:
    1.•映射语句文件中的所有 select 语句将会被缓存。
    2.•映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
    3.•缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
    ......
    -->
    <cache />
    
    <!-- 用来定义可重用的SQL代码段 -->
    <sql id="selectProdSQL">
       PRODID,PRODSERIAL,PRODNAME,CATEGORYNAME,PRODSPEC,PRODPRICE,PRODDESC,PRODIMAGE,ISNEW,ISRECOMMEND,ISSHOW,USERNAME,HANDLETIME,PRODTHUMBNAIL
    </sql>

    <!--以单个对象方式返回-->
    <select id="getProduct" resultType="Product" parameterType="int">
    select <include refid="selectProdSQL"/>
      FROM PRODUCT
    WHERE PRODID = #{prodId}
    </select>

    <resultMap type="Product" id="prodByCategoryMap">  
        <id property="prodId" column="prodId"/>  
        <!--有需要做数据库到实体类名称转换的,可以写在这里-->
        <!--
        <result property="objname" column="dbname"/>
        -->
    </resultMap>  

    <!--以List方式返回多个结果-->
    <select id="getProdByCategory" resultMap="prodByCategoryMap" parameterType="string">
    select <include refid="selectProdSQL"/>
      FROM PRODUCT
    WHERE CATEGORYNAME = #{categoryName}
    </select>
    
    <!--Oracle的实现自增长主键的方式-->
    <!--对于数据库中允许为空的字段,需要在这里指定字段类型,因为MyBatis不知道你传入的 null 参数对应的 jdbc 类型是什么;如何没有指定,则需要在插入数据时全部字段都要设置值,哪怕是空值!-->
    <insert id="insertProduct" parameterType="Product">
    <selectKey keyProperty="prodId" resultType="int" order="BEFORE">
      select SEQ_PRODUCT.nextval from DUAL
    </selectKey>
      INSERT INTO PRODUCT (PRODID,PRODSERIAL,PRODNAME,CATEGORYNAME,PRODSPEC,PRODPRICE,PRODDESC,PRODIMAGE,ISNEW,ISRECOMMEND,ISSHOW,USERNAME,HANDLETIME,PRODTHUMBNAIL)
      VALUES(#{prodId}, #{prodSerial,jdbcType=VARCHAR}, #{prodName}, #{categoryname,jdbcType=VARCHAR}, #{prodSpec,jdbcType=VARCHAR}, #{prodPrice,jdbcType=DOUBLE}, 
      #{prodDesc,jdbcType=VARCHAR}, #{prodImage,jdbcType=VARCHAR}, #{isNew}, #{isRecommend}, #{isShow}, #{username}, #{handletime,jdbcType=DATE}, #{prodThumbnail,jdbcType=VARCHAR})
    </insert>

    <update id="updateProduct" parameterType="Product">
      update PRODUCT set
        PRODSERIAL = #{prodSerial,jdbcType=VARCHAR},

        PRODNAME = #{prodName},
        CATEGORYNAME = #{categoryname,jdbcType=VARCHAR},
        PRODSPEC = #{prodSpec,jdbcType=VARCHAR},
        PRODPRICE = #{prodPrice,jdbcType=DOUBLE},
        PRODDESC = #{prodDesc,jdbcType=VARCHAR},
        PRODIMAGE = #{prodImage,jdbcType=VARCHAR},
        ISNEW = #{isNew},
        ISRECOMMEND = #{isRecommend},
        ISSHOW = #{isShow},
        USERNAME = #{username},
        HANDLETIME = #{handletime,jdbcType=DATE},
        PRODTHUMBNAIL = #{prodThumbnail,jdbcType=VARCHAR}
      where PRODID = #{prodId}
    </update>

    <delete id="deleteProduct" parameterType="int">
      delete from PRODUCT where PRODID = #{prodId}
    </delete>
</mapper>

4.6 创建mapper接口实现类

package com.clzhang.sample.struts2.mapper.impl;

import java.util.*;

import org.apache.ibatis.session.SqlSession;

import com.clzhang.sample.struts2.mapper.MyBatisSessionFactory;
import com.clzhang.sample.struts2.mapper.ProductMapper;
import com.clzhang.sample.struts2.mapper.entity.ProductBean;

/**
 * 数据库操作实现类
 * @author acer
 *
 */
public class ProductMapperImpl implements ProductMapper {

    /**
     * 新加单个数据
     */
    public void insertProduct(ProductBean product) {
        SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession();
        try {
            session.insert("ProductMapper.insertProduct", product);
            session.commit();
        } finally {
            session.close();
        }
    }
    
    /**
     * 更新单条数据
     */
    public void updateProduct(ProductBean product) {
        SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession();
        try {
            session.update("ProductMapper.updateProduct", product);
            session.commit();
        } finally {
            session.close();
        }
    }
    
    /**
     * 删除单条数据
     */
    public void deleteProduct(int prodId){
        SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession();
        try {
            session.delete("ProductMapper.deleteProduct", prodId);
            session.commit();
        } finally {
            session.close();
        }
    }
    
    /**
     * 查询单条数据
     */
    public ProductBean getProduct(int prodId) {
        SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession();
        ProductBean product = null;
        try {
            product = (ProductBean)session.selectOne("ProductMapper.getProduct", prodId);
        } finally {
            session.close();
        }
        
        return product;
    }
    
    /**
     * 查询批量数据
     */
    public List<ProductBean> getProdByCategory(String categoryName) {
        Map<String,Object> params = new HashMap<String ,Object>();
        params.put("categoryName", categoryName);

        SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession();
        List<ProductBean> list = null;
        try {
            list = session.selectList("ProductMapper.getProdByCategory", params);
        } finally {
            session.close();
        }
        
        return list;
    }
}

4.7 创建获取SessionFactory的通用类

package com.clzhang.sample.struts2.util;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * SqlSessionFactory 应该在你的应用执行期间都存在。没有理由来处理或重新创建它。
 * 所以定义一个通用类,所以获取SqlSessionFactory句柄的程序都从这儿获取。
 * @author acer
 *
 */
public class MyBatisSessionFactory {

    private static final String MYBATIS_CONFIG_FILENAME = "config/mybatis-config.xml";
    private static SqlSessionFactory sqlSessionFactory = null;

    static {
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader(MYBATIS_CONFIG_FILENAME);
        } catch (IOException e) {
            throw new RuntimeException("Get resource error:"+MYBATIS_CONFIG_FILENAME, e);
        }

        // 一旦你创建了 SqlSessionFactory 后,SqlSessionFactoryBuilder这个类就不需要存在了。
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    }
    
    public static SqlSessionFactory getSqlSessionFactory(){   
        return sqlSessionFactory;   
    }
    
}

4.8 创建测试类到了这里,代码就变得非常简单了

package com.clzhang.sample.struts2.test;

import java.util.List;

import org.junit.Test;

import com.clzhang.sample.struts2.mapper.entity.ProductBean;
import com.clzhang.sample.struts2.mapper.ProductMapper;
import com.clzhang.sample.struts2.mapper.impl.ProductMapperImpl;

/**
 * 因为由ProductMapperImpl之类的数据库实现类实现了详细的数据库提交接口;
 * 所以此处的代码非常简单,就是Java对象的操作而已。
 * @author acer
 *
 */
public class MyBatisTest2 {
    private ProductMapper productMapper = new ProductMapperImpl();

    @Test
    public void testInsert() {
        ProductBean entity = new ProductBean();
        
        // 注意:因数的ProductMapper.xml中已经设置了字段空值时如果处理,所以此处不一定要设置实体的所有属性。
//        entity.setProdSerial("BT072-8(K8)");
        entity.setProdName("相册");
//        entity.setCategoryname("套件");
//        entity.setProdSpec("230*200 240*220cm");
//        entity.setProdPrice(12.0);
//        entity.setProdDesc("面料:粘丝与棉交织......");
//        entity.setProdImage("/upload/product/201211260815461.jpg");
        entity.setIsNew(0);
        entity.setIsRecommend(0);
        entity.setIsShow(0);
        entity.setUsername("admin");
//        entity.setHandletime(new java.sql.Timestamp(new java.util.Date().getTime()));
//        entity.setProdThumbnail("/upload/product/20121126081626394.jpg");
        
        productMapper.insertProduct(entity);
        System.out.println("新加的实体主键:" + entity.getProdId());
    }

    @Test
    public void testUpdate() {
        int pridId = 34;
        
        ProductBean entity = productMapper.getProduct(pridId);
        entity.setProdName("新产品");
        
        productMapper.updateProduct(entity);
    }

    @Test
    public void testDelete() {
        int prodId = 35;

        productMapper.deleteProduct(prodId);
    }

    @Test
    public void getProduct() {
        int pridId = 36;
        
        ProductBean entity = productMapper.getProduct(pridId);
        if(entity != null){
            System.out.println(entity.getProdName());
        }
        else{
            System.out.println("prodId不存在!" + pridId);
        }
    }

    @Test
    public void getProdByCategoryName() {
        List<ProductBean> list = productMapper.getProdByCategory("套件");
        for(ProductBean entity: list) {
            System.out.println(entity.getProdName());
        }
    }
}

输出结果:

新加的实体主键:6
皇室风范
图门
美好心情
123
大雅风尚

原文地址:https://www.cnblogs.com/nayitian/p/2952976.html