Mybatis初步

来源:互联网 发布:手机订车票软件 编辑:程序博客网 时间:2024/06/06 04:06

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

1.准备开发环境

1、创建测试项目,普通java项目或者是JavaWeb项目均可,如下图所示:
这里写图片描述
添加相应的jar包:
mybatis-3.4.4.jar
mysql-connector-java-5.1.30-bin.jar
jsbc.prop[mysql数据库信息配置文件]:

#dbConfig#Mon Jul 31 07:54:49 CST 2017url=jdbc:mysql://localhost:3306/t_marketpassword=rootdriver=com.mysql.jdbc.Driverusername=root

mybatis-config.xml[mybatis配资信息文件]:

<?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属性,properties和java的.properties的配置文件有关;  配置properties的resource指定.properties的路径;  然后再在properties标签下配置property的name和value,  则可以替换.properties文件中相应属性值。 -->  <properties resource="jsbc.prop" />  <!--typeAliases 必须在properties之后声明 -->  <!-- typeAliases类型别名,类型别名是Java 类型的简称;它仅仅只是关联到XML 配置,简写冗长的JAVA 类名; -->  <typeAliases>    <!-- 定义别名User为javaBean类com.my.market.model.User -->    <typeAlias alias="User" type="com.my.market.model.User"/>  </typeAliases><!-- environments环境,MyBatis 可以配置多个环境。这可以帮助你SQL 映射对应多种数据库等; -->  <environments default="development">    <!-- 默认开发环境 -->    <environment id="development">      <!-- 事务管理器 -->      <transactionManager type="JDBC"/>      <!-- 数据源 -->      <dataSource type="POOLED">        <property name="driver" value="${driver}"/>        <property name="url" value="${url}"/>        <property name="username" value="${username}"/>        <property name="password" value="${password}"/>      </dataSource>    </environment>  </environments>  <!-- 将model中类对应的mapper文件加入配置中-->  <!-- mappers映射器,这里是告诉MyBatis 去哪寻找映射SQL 的语句;可以使用类路径中的资源引用,或者使用字符,输入确切的URL引用; -->  <mappers>    <mapper resource="com/my/market/model/User.xml"/>  </mappers></configuration>  

2.定义表所对应的实体类,如下图所示:

这里写图片描述
User.java[实体类User]:

package com.my.market.model;public class User {    private int id;    private String username;    private String password;    private String nickname;    private int type;    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getNickname() {        return nickname;    }    public void setNickname(String nickname) {        this.nickname = nickname;    }    public int getType() {        return type;    }    public void setType(int type) {        this.type = type;    }    public int getId() {        return id;    }    public String getUsername() {        return username;    }    public User(int id, String username, String password, String nickname, int type) {        this.id = id;        this.username = username;        this.password = password;        this.nickname = nickname;        this.type = type;    }    public User() {    }    @Override    public String toString() {        return "User [id=" + id + ", username=" + username + ", password=" + password + ", nickname=" + nickname                + ", type=" + type + "]";    }}

User.xml[User类对应的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"><!-- com.my.market.model.User实体类对应的mapper文件,namespace限定名字空间避免重复 --><mapper namespace="com.my.market.model.User">    <!-- 通过[namespace.id 即 com.my.market.model.User.add]进行add的插入方法的调用 -->    <insert id="add" parameterType="User">        insert into t_user(username, password, nickname, type)         values(#{username},#{password},#{nickname},#{type})    </insert>    <update id="update" parameterType="User">        update t_user set password=#{password},nickname=#{nickname},type=#{type} where id=#{id}    </update>    <delete id="delete" parameterType="int">        delete from t_user where id=#{id}    </delete>    <select id="select" parameterType="int" resultType="User">        select * from t_user where id=#{id}    </select>    <!-- 使用User别名 -->    <select id="list" resultType="User">        select * from t_user    </select></mapper>

3.Junit测试类

MyBatisUtil.java[Mybatis工具类用来获取session]:

package com.my.market.util;import java.io.Closeable;import java.io.IOException;import java.io.InputStream;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class MyBatisUtil {    private static final String RESOURCE = "mybatis-config.xml";    private static SqlSessionFactory factory;    static {        try {            //1.创建配置文件(mybatis-config.xml)的输入流            InputStream iStream=Resources.getResourceAsStream(RESOURCE);            //2.创建SqlSessionFactory            factory=new SqlSessionFactoryBuilder().build(iStream);        } catch (IOException e) {            e.printStackTrace();        }    }    private MyBatisUtil() {    }    public static SqlSession getSession() {        //3.创建SqlSession        return factory.openSession();    }    public static void close(SqlSession session) {        if(null!=session) {            session.close();        }    }}

TestMyBatisJunit.java[MyBatis Junit测试类]:

package com.my.market.test;import static org.junit.Assert.*;import java.io.IOException;import java.io.InputStream;import java.util.List;import javax.jws.soap.SOAPBinding.Use;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;import com.my.market.model.User;import com.my.market.util.MyBatisUtil;public class TestMyBatisJunit {    private static final String RESOURCE = "mybatis-config.xml";    @Test    public void testDelete() {        InputStream is=null;        try {            is = Resources.getResourceAsStream(RESOURCE);        } catch (IOException e) {            e.printStackTrace();        }        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);        SqlSession session=factory.openSession();        System.out.println(User.class.getName());        session.delete(User.class.getName()+".delete", 9);        session.commit();        session.close();    }    @Test    public void testLoad() {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            User user=(User)session.selectOne(User.class.getName()+".select", 1);            System.out.println(user);        }finally {            MyBatisUtil.close(session);        }    }    @Test    public void testAdd() {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            User user=new User(0, "tangseng1", "123", "唐僧1", 0);            session.insert(User.class.getName()+".add", user);            session.commit();        }catch(Exception e) {            session.rollback();            e.printStackTrace();        }        finally {            session.close();        }    }    @Test    public void testList() {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            List<User> userList=session.selectList(User.class.getName()+".list");            for(User u: userList) {                System.out.println(u);            }        }finally {            MyBatisUtil.close(session);        }    }}

4.工具,基础类

1.BaseDao.java[所有dao的基本父类]:

package com.my.market.dao;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.ibatis.session.SqlSession;import com.my.market.model.Address;import com.my.market.model.Page;import com.my.market.model.SystemContext;import com.my.market.model.User;import com.my.market.util.DBUtil;import com.my.market.util.DaoUtil;import com.my.market.util.LogUtil;import com.my.market.util.MyBatisUtil;public class BaseDao<T> {    public BaseDao() {//      //依赖注入,对于子类需要set的对象,例如setUserDao//      Method[] methods=this.getClass().getDeclaredMethods();//      //error:unknow function//      //this.setUserDao(null);//      System.out.println(Arrays.toString(methods));//      for(Method m: methods) {//          String methodName =m.getName();//          if(methodName.startsWith("set")) {//              LogUtil.printLog(m);//              String name=methodName.substring(3);//              LogUtil.printLog(methodName+":  "+name);//              Object obj=DaoUtil.createDaoFactory().getDao(name);//              try {//                  m.invoke(this, obj);//              } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {//                  e.printStackTrace();//              }//          }//      }        DaoUtil.diDao(this);    }    public void add(T obj) {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            session.insert(obj.getClass().getName()+".add", obj);            session.commit();        }catch(Exception e) {            session.rollback();            e.printStackTrace();        }finally {            MyBatisUtil.close(session);        }    }    public <Type> void add(String sqlId, Type obj) {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            session.insert(sqlId, obj);            session.commit();        }catch(Exception e) {            session.rollback();            e.printStackTrace();        }finally {            MyBatisUtil.close(session);        }    }    public void update(T obj) {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            session.update(obj.getClass().getName()+".update", obj);            session.commit();        }catch(Exception e) {            session.rollback();            e.printStackTrace();        }finally {            MyBatisUtil.close(session);        }    }    public void delete(Class<T> clz, int id) {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            session.delete(clz.getName()+".delete", id);            session.commit();        }catch(Exception e){            session.rollback();            e.printStackTrace();        }finally {            MyBatisUtil.close(session);        }    }    public void delete(String sqlId, Map<String, Object> params) {        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            session.delete(sqlId, params);            session.commit();        }catch(Exception e){            session.rollback();            e.printStackTrace();        }finally {            MyBatisUtil.close(session);        }    }    public T load(Class<T> clz, int id) {        SqlSession session=null;        T obj=null;        try {            session=MyBatisUtil.getSession();            obj= session.selectOne(clz.getName()+".load", id);        }finally {            MyBatisUtil.close(session);        }        return obj;    }    public T loadBySqlId(String sqlId, Map<String, Object> params) {        SqlSession session=null;        T obj=null;        try {            session=MyBatisUtil.getSession();            obj= session.selectOne(sqlId, params);        }finally {            MyBatisUtil.close(session);        }        return obj;    }    public T loadBySqlId(String sqlId, Object param) {        SqlSession session=null;        T obj=null;        try {            session=MyBatisUtil.getSession();            obj= session.selectOne(sqlId, param);        }finally {            MyBatisUtil.close(session);        }        return obj;    }    public Page<T> find(Class<T> clz, Map<String, Object> params){        int pageSize =SystemContext.getMaxPageItems();        int pagerOffset=SystemContext.getPagerOffset();        String order=SystemContext.getOrder();        String condition=SystemContext.getCondition();        Page<T> page = null;        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            if(null==params) {                params=new HashMap<>();            }            params.put("pageSize", pageSize);            params.put("pagerOffset", pagerOffset);            params.put("order", order);            params.put("condition", condition);            List<T> objList=session.selectList(clz.getName()+".find", params);            int totalRecord=session.selectOne(clz.getName()+".find_count", params);            page=new Page<T>(pagerOffset/pageSize+1, totalRecord, pageSize,                    totalRecord/pageSize+(totalRecord%pageSize==0? 0:1), objList);        }finally {            MyBatisUtil.close(session);        }        return page;    }    public Page<T> find(String sqlId, Map<String, Object> params){        int pageSize =SystemContext.getMaxPageItems();        int pagerOffset=SystemContext.getPagerOffset();        String order=SystemContext.getOrder();        String condition=SystemContext.getCondition();        Page<T> page = null;        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            if(null==params) {                params=new HashMap<>();            }            params.put("pageSize", pageSize);            params.put("pagerOffset", pagerOffset);            params.put("order", order);            params.put("condition", condition);            List<T> objList=session.selectList(sqlId, params);            LogUtil.printLog(sqlId);            LogUtil.printLog(sqlId+"_count");            int totalRecord=session.selectOne(sqlId+"_count", params);            page=new Page<T>(pagerOffset/pageSize+1, totalRecord, pageSize,                    totalRecord/pageSize+(totalRecord%pageSize==0? 0:1), objList);        }finally {            MyBatisUtil.close(session);        }        return page;    }    public List<T> listBySqlId(String sqlId, Map<String, Object> params){        List<T> objList= null;        SqlSession session=null;        try {            session=MyBatisUtil.getSession();            if(null==params) {                params=new HashMap<>();            }            objList=session.selectList(sqlId, params);        }finally {            MyBatisUtil.close(session);        }        return objList;    }}

2.DaoUtil.java[工厂模式的获取,依赖注入]:

package com.my.market.util;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;import com.my.market.dao.IFactoryDao;import com.my.market.model.MarketDi;public class DaoUtil {    public static void main(String[] args) {        createDaoFactory();    }    public static IFactoryDao createDaoFactory() {        Properties properties= PropertiesUtil.getDaoProp();        String factoryName=properties.getProperty("factory");        LogUtil.printLog(factoryName);        IFactoryDao daoFactory=null;        try {            Class<?> clz=Class.forName(factoryName);            String methodName="getInstance";            Method method=clz.getMethod(methodName);            daoFactory =(IFactoryDao)method.invoke(clz);        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException |                IllegalArgumentException | InvocationTargetException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        LogUtil.printLog(daoFactory);        return daoFactory;    }    public static void diDao(Object obj) {        //get the class from the object which will set value into it        Class<?> clz=obj.getClass();        //get declared methods from the class        Method[] methods=clz.getDeclaredMethods();        for(Method m: methods) {            //if the Method has 'MarketDi' annotation, it show the Method want to get a object            if(m.isAnnotationPresent(MarketDi.class)) {                MarketDi aDi=m.getAnnotation(MarketDi.class);                String objName=aDi.value();                if(null==objName || "".equals(objName)) {                    String methodName=m.getName();                    LogUtil.printLog(methodName+": "+objName);                    if(methodName.startsWith("set")) {                        LogUtil.printLog(m);                        objName=methodName.substring(3);                    }                }                //get className from properties file, invoke the Method, set the object into it                try {                    Properties properties=PropertiesUtil.getDaoProp();                    String className=properties.getProperty(objName);                    LogUtil.printLog(objName+": "+className);                    Object object=Class.forName(className).newInstance();                    m.invoke(obj, object);                } catch (InstantiationException | IllegalAccessException | ClassNotFoundException |                        IllegalArgumentException | InvocationTargetException e) {                    e.printStackTrace();                }            }        }    }}

3.PropertiesUtil.java[属性读取工具]:

package com.my.market.util;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.Properties;import sun.security.jca.GetInstance;public class PropertiesUtil {    private static Properties dBProperties=null;    private static Properties daoProperties=null;    private static final String CONFIG_FILE="dbConfi.prop";    private static final String DAO_FILE="dao.prop";    private PropertiesUtil() {    }    public static Properties getInstance() {        if(null==dBProperties) {            synchronized (PropertiesUtil.class) {                if(null==dBProperties) {                    dBProperties=new Properties();//                  try(//                      FileInputStream fin=new FileInputStream("/"+CONFIG_FILE);//                  ){                    try{                        File f1=new File("test.txt");                        LogUtil.printLog(f1.getAbsolutePath());                        LogUtil.printLog(PropertiesUtil.class.getResource(CONFIG_FILE));                        dBProperties.load(PropertiesUtil.class.getResourceAsStream(CONFIG_FILE));                    }catch (Exception e) {                        e.printStackTrace();                        System.exit(-1);                    }                }            }        }        return dBProperties;    }    public static Properties getDaoProp() {        try {            if(null==daoProperties) {                synchronized(PropertiesUtil.class) {                    if(null==daoProperties) {                        daoProperties=new Properties();                        daoProperties.load(PropertiesUtil.class.getClassLoader().getResourceAsStream(DAO_FILE));                    }                }            }        }catch(IOException e) {            e.printStackTrace();        }        return daoProperties;    }}

DaoFactoryByProperties.java[通过properties获取Dao工厂]:

package com.my.market.dao;import java.util.HashMap;import java.util.Map;import java.util.Properties;import com.my.market.util.LogUtil;import com.my.market.util.PropertiesUtil;public class DaoFactoryByProperties implements IFactoryDao {    private static DaoFactoryByProperties factory=new DaoFactoryByProperties();    private static Map<String, Object> daoMap=new HashMap<>();    private DaoFactoryByProperties() {    }    public static IFactoryDao getInstance() {        return factory;    }    @Override    public Object getDao(String name) {        Object object=null;        Properties properties=PropertiesUtil.getDaoProp();        String daoClassName=properties.getProperty(name);        LogUtil.printLog(daoClassName);        if(daoMap.containsKey(daoClassName)) {            return daoMap.get(daoClassName);        }        try {            object=Class.forName(daoClassName).newInstance();            daoMap.put(daoClassName, object);        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {            e.printStackTrace();        }        return object;    }}

5.mybatis使用步骤

操作步骤
1、将jar导入到项目
2、创建Config.xml文件用来指定相应的数据库连接信息
这里写图片描述
这里写图片描述
3、创建mapp.xml文件
这里写图片描述
4、创建SqlSessionFactory
这里写图片描述
5、根据factory获取session
这里写图片描述
6、直接根据session来执行相应的操作
这里写图片描述

6.map文件中的insert,update,delete,select

insert标签表示添加相应的对象信息,paramterType表示添加的对象类型
这里写图片描述
update表示更新操作,delete表示删除操作
这里写图片描述
select表示查询操作,可以查询列表或者单个对象
这里写图片描述
相应的调用方式
这里写图片描述

7.mapp.xml中两种引用

1、#{xxx}这种方式会自动将这个值替换为PreparedStatment中?来使用,如果是字符串会自动加上引号,对于排序而言就无法操作
2、${xx}这种方式叫做完全替换,直接将字符串完整的替换到这个位置,完全替换的方式可能会出现SQL注入的安全隐患。建议在参数中不要使用这种方式。但是如果使用在排序中没有任何影响
这里写图片描述

8.动态SQL语句

在mapp.xml文件中可能会根据一些参数值的不同而动态的产生相应的SQL语句,此时就需要进行动态SQL语句的设定
这里写图片描述

9.Resultmap的使用

使用ResultMap可以完成相应的结果集自定义输出
这里写图片描述
ResultMap还可以完成一些外键对对象的映射
这里写图片描述
使用以上映射方式有一个致命的缺点:所谓的N+1问题
使用关联查询来解决N+1问题
这里写图片描述