功能:实现Mapper接口,封装SqlSession之类的调用,进一步简化程序的调用,就像操作普通对象一样,感觉不到后台数据库
预备:请先阅读重新整理,MyBatis3之初步,实体的增加、修改、删除、查询
一、目录结构
com.clzhang.mybatis.entity ProductBean.java MyBatis的entity类 com.clzhang.mybatis.mapper MyBatisSessionFactory.java SqlSessionFactory获取类 com.clzhang.mybatis.mapper ProductMapper.java MyBatis的mapper处理类 com.clzhang.mybatis.mapper.impl ProductMapperImpl.java ProductMapper的接口实现类 com.clzhang.test MyBatisTest2.java 测试类,最终应该是在service的package中调用mapper中的方法。 resourcesconfig mybatis-config.xml MyBatis的配置文件 resourcescomclzhangmybatismapper ProductMapper.xml MyBatis的mapper配置文件
二、假定数据库已经创建,表结构也已经创建,并且有测试数据
CREATE TABLE MEMBER_USER ( ID NUMBER NOT NULL PRIMARY KEY, NAME VARCHAR2(30), PERSONMOBILE VARCHAR2(20), ADDRESS VARCHAR2(255), AGE NUMBER); CREATE SEQUENCE SEQ_MEMBER_USER;
三、具体步骤
1. 创建entity类
package com.clzhang.mybatis.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; } }
2. 创建mapper接口类
package com.clzhang.mybatis.mapper; import java.util.*; import com.clzhang.mybatis.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); }
3. 创建MyBatisSessionFactory类
package com.clzhang.mybatis.mapper; import java.io.*; 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 { try { InputStream inputStream = Resources.getResourceAsStream(MYBATIS_CONFIG_FILENAME); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { throw new RuntimeException("Get resource error:"+MYBATIS_CONFIG_FILENAME, e); } } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
4. 创建mapper接口实现类
package com.clzhang.mybatis.mapper.impl; import java.util.*; import org.apache.ibatis.session.SqlSession; import com.clzhang.mybatis.mapper.MemberUserMapper; import com.clzhang.mybatis.mapper.MyBatisSessionFactory; import com.clzhang.mybatis.mapper.ProductMapper; import com.clzhang.mybatis.entity.ProductBean; /** * 数据库操作实现类 * @author acer * */ public class ProductMapperImpl implements ProductMapper { /** * 新加单个数据 */ public void insertProduct(ProductBean product) { SqlSession session = MyBatisSessionFactory.getSqlSessionFactory().openSession(); try { // 如果ProductMapper.xml中定义namespace为长文件名,则用传统方式调用 // 以下的updateProduct/deleteProduct,以此类推 // ProductMapper mapper = session // .getMapper(ProductMapper.class); // mapper.insertProduct(product); // // 如果ProductMapper.xml中定义namespace为短文件名,则可以用如下方式调用 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; } }
5. 修改mybatis-config.xml配置文件,增加Product实体与Mapper的描述
<?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> <settings> <setting name="cacheEnabled" value="false" /> <setting name="useGeneratedKeys" value="true" /> <setting name="defaultExecutorType" value="REUSE" /> </settings> <typeAliases> <typeAlias alias="MemberUser" type="com.clzhang.mybatis.entity.MemberUserBean"/> <typeAlias alias="Product" type="com.clzhang.mybatis.entity.ProductBean"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/> <property name="username" value="mytest"/> <property name="password" value="test001"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/clzhang/mybatis/mapper/MemberUserMapper.xml" /> <mapper resource="com/clzhang/mybatis/mapper/ProductMapper.xml" /> </mappers> </configuration>
6. 创建ProductMapper.xml配置文件
<?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"> <!-- 1.namespace的值可以设置得非常短比如:ProductMapper,如果项目不大的情况下,可以考虑这样使用。 好处是在Java代码如下调用即可:session.insert("ProductMapper.insertProduct", product); 2.如果项目非常大的话(或者是与Spring整合),那么还是建议使用长文件名做标识。 --> <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>
7. 创建测试类,到了这里,代码就变得非常简单了
package com.clzhang.test; import java.util.List; import org.junit.Test; import com.clzhang.mybatis.entity.ProductBean; import com.clzhang.mybatis.mapper.ProductMapper; import com.clzhang.mybatis.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 = 23; ProductBean entity = productMapper.getProduct(pridId); entity.setProdName("新产品"); productMapper.updateProduct(entity); } // @Test public void testDelete() { int prodId = 24; productMapper.deleteProduct(prodId); } // @Test public void getProduct() { int pridId = 23; 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()); } } }
四、单独测试各个模块
解除注释JUnit各单元,然后键盘输入:alt+shift+X,T,分别进行测试。