Mybatis学习笔记之二:在项目中使用Mybatis

来源:互联网 发布:逆战磁暴矩阵难出吗 编辑:程序博客网 时间:2024/05/21 20:23

在开发之前,需要做好以下准备工作:

1、JDK以及IDE已经配置完成

2、数据库安装完成

3、相关依赖(Mybatis的jar文件以及JDBC的驱动)

笔者这儿使用的是JDK8,开发工具STS,数据库Mysql 5.6.26,Mybatis版本3.3。

准备好上诉工作就可以开始编写了。

1、创建数据库以及表


2、创建项目并将依赖的jar包加入到类路径中。

3、编写mybatis的配置文件mybatis-config.xml(名字可以随意命名)以及数据库连接配置文件

db.properties

url = jdbc:mysql://localhost:3306/ym_mybatisuser = rootpassword = 951001driver = com.mysql.jdbc.Driver
mybatis-config.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><!--这个properties可以引入外部的配置文件  --><properties resource="jdbc.properties"/><!--配置别名,后面会讲有什么作用  --><typeAliases><package name="cn.yamikaze.model"/></typeAliases>    <!--配置默认的开发環境  --><environments default="development"><!--可以配置多个开发环境,但是外层的默认开发环境必须是配置的其中一个环境  --><environment id="development"><!--配置事务管理,这儿使用JDBC的事务  --><transactionManager type="JDBC"/><dataSource type="POOLED"><!--配置与数据库的连接  --><!--使用${}获取前面引入的配置文件中的值  --><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${user}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--配置实体类的映射文件(实体类的sql语句存放的文件)--><mappers><mapper resource="cn/yamikaze/model/UserMapper.xml"/></mappers></configuration>

4、编写实体类(略)以及实体类的配置文件,配置文件名最好以mapper结尾。

UserMapper.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"><mapper namespace="org.yamikaze.dao.impl.IUserDao"><!--命名空间不能重复-->    <!--insert、update、delete、select标签分别对应数据库的相应语句,在同一个配置文件中id属性必须唯一     parameterType表示传进来的参数类型,Mybatis内置了一些类型,比如int、map、string等。而useGenerateKeys     表示会使用JDBC的getGeneratedKeys方法取出数据库自动递增的主键。如果配置了keyProperty属性,     会自动将取出来的主键注入到keyProperty配置的属性中,但这只对insert和update有效-->    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">        <!--#{}表示一个占位符,类似于JDBC中PreparedStatement的setParameter方法,        中间的值会在传进来的对象中自动查找,例如user对象中有username属性,那么使用#{username}        就会到user中查找username属性,如果没有找到,就会抛出错误-->        insert into t_user(username,password,sex) values(#{username},#{password},#{sex})    </insert>    <select id="loadByUsername" parameterType="string" resultType="User">        SELECT * FROM  t_user WHERE username = #{username}    </select></mapper>
还记得在Mybatis-config.xml中配置的typeAliases吗?这儿我们写的参数对象是User,因为配置了别名,所以不用写出User的全称限定名。前面配置的是package=org.yamikaze.model,那么这个包下面的所有类都可以直接使用简单名称。当然你也可以使用typeAlias配置别名,如果有多个实体类包,配置多个package。

userMapper配置文件只写了插入和查找,可以自己补全删除、更新语句。

5、使用Mybatis操纵数据

    使用Mybatis有好几种方式,先介绍最基本的。

    5.1、直接使用Mybatis的session进行操作。

    public static void main(String[] args) {        insert();    }    public static void insert() {        InputStream is = null;        SqlSessionFactory factory = null;        SqlSession session = null;        try {            /*读取Mybatis的配置文件,这儿使用的是Mybatis的Resources类,但你可以使用InputStream*/            is = Resources.getResourceAsStream("mybatis-config.xml");            /*通过配置文件获取Mybatis的工场*/            factory = new SqlSessionFactoryBuilder().build(is);            /*通过工场打开一个会话*/            session = factory.openSession();            /*创建实体类对象,并设入相应属性*/            User user = new User();            user.setUsername("zs3");            user.setPassword("123");            user.setSex("man");            /*由于是插入数据,这儿使用insert方法,相应的有selectOne方法、selectList、delete方法*/            /*第一个参数表示哪个命名空间里的哪个方法(配置中填写的id属性,所以一个配置文件不能有相同的id)            * user是传递的参数*/            session.insert("org.yamikaze.dao.impl.IUserDao.save",user);            /**             * 注意:如果调用的方法会修改数据库的数据,一定要记得提交,因为Mybatis使用的是JDBC的事务,             * JDBC是默认自动提交事务的             * 但Mybatis在通过JDBC获取连接时关闭了自动提交             */            session.commit();            /*因为设置了useGeneratedKeys和keyProperty属性,会自动将ID注入到user对象中*/            System.out.print(user.getId());        } catch (IOException e) {            /*修改数据时发生异常记得回滚数据*/            if(session!=null) session.rollback();        } finally {            /*关闭session*/            if(session!=null) session.close();        }    }
    5.2、使用类的方式,并且对5.1的方式简化一下,因为在整个程序运行期间,可能会获取多个session,但是读取配置和获取工厂只会获取一次,所以我们可以将这部分提取出来。

    先写一个工具类SqlSessionUtil.java

package org.yamikaze.utils;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 java.io.IOException;import java.io.InputStream;/** * Created by yamikaze */public class SqlSessionUtil {    private static SqlSessionFactory factory;    private SqlSessionUtil(){}    static {        init();    }    private static void init(){        try {            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");            factory = new SqlSessionFactoryBuilder().build(is);        } catch (IOException e) {            //            System.out.println("读取配置错误");        }    }    public static SqlSession openSession() {        return factory.openSession();    }    public static void closeSession(SqlSession session) {        if(session!=null) session.close();    }    public static void rollback(SqlSession session) {        if(session!=null) session.rollback();    }}
    编写DAO

    IUserDao.java

package org.yamikaze.dao.impl;import org.yamikaze.model.User;/** * Created by yamikaze on 2017/7/5. */public interface IUserDao {    public void save(User user);    public User loadByUsername(String username);}

实现类UserDao.java

package org.yamikaze.dao.impl;import org.apache.ibatis.session.SqlSession;import org.yamikaze.model.User;import org.yamikaze.utils.SqlSessionUtil;import java.io.IOException;/** * Created by yamikaze on 2017/7/11. */public class UserDao implements  IUserDao{    @Override    public User loadByUsername(String username) {        return null;    }    @Override    public void save(User user) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            session.insert("org.yamikaze.dao.impl.IUserDao.save",user);            session.commit();        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {            SqlSessionUtil.closeSession(session);        }    }}
save方法变得简单了,但现在问题是session的insert方法需要一个id,向上面那样写肯定是不方便的,我们知道org.yamikaze.dao.impl.IUserDao是命名空间,而save是id,如果所有的mapper配置文件中没有重复的id,可以不加上命名空间,如果有就要加上命名空间,但是这种加法不是很方便,我们可以将命名空间改为实体类的全称限定名,然后在代码中使用这种方式:

@Override    public void save(User user) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            session.insert(User.class.getName()+".save",user);//与调用session.insert("org.yamikaze.model.User.save",user);是一致的            session.commit();        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {            SqlSessionUtil.closeSession(session);        }    }
这种方式又有一个问题存在,那就是每个实体类都会有save、delete、update等共通的方法,然后你会发现,就方法的参数以及id不同,那么可以使用以下方式再简化一下:

我们约定统一配置,插入数据id为save、删除delete、更新update、列表list。然后编写一个IBaseDao.java

package org.yamikaze.dao.impl;import java.util.List;/** * Created by yamikaze on 2017/7/11. */public interface IBaseDao<T> {    void save(T t);    void update(T t);    void delete(int id);    T load(int id);    List<T> listAll();}

这儿使用了泛型,因为不知道实际添加时是什么类型的对象。

继续编写BaseDao.java
package org.yamikaze.dao.impl;import org.apache.ibatis.session.SqlSession;import org.yamikaze.utils.SqlSessionUtil;import java.lang.reflect.*;import java.util.List;/** * Created by yamikaze on 2017/7/11. */public class BaseDao <T> implements IBaseDao<T>{    private Class clz;    /**     * 获取T.class对象,      * @return     */    protected Class getClz() {        Type genType = getClass().getGenericSuperclass();        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();        clz = (Class) params[0];        return clz;    }    @Override    public T load(int id) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            return session.selectOne(getClz().getName()+".load",id);            //查找数据,可以不用提交        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {        }        return null;    }    @Override    public List<T> listAll() {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            return session.selectList(getClz().getName()+".listAll");        } catch (Exception e) {        } finally {            SqlSessionUtil.closeSession(session);        }        return null;    }    @Override    public void save(T t) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            session.insert(getClz().getName()+".save",t);            session.commit();        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {            SqlSessionUtil.closeSession(session);        }    }    @Override    public void delete(int id) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            session.delete(getClz().getName()+".delete",id);            session.commit();        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {            SqlSessionUtil.closeSession(session);        }    }    @Override    public void update(T t) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            session.update(getClz().getName()+".update",t);            session.commit();        } catch (Exception e) {            SqlSessionUtil.rollback(session);        } finally {            SqlSessionUtil.closeSession(session);        }    }}
IBaseDao与BaseDao是针对所有对象的共通的CRUD方法。

继续编写IUserDao.java

package org.yamikaze.dao.impl;import org.yamikaze.model.User;/** * Created by yamikaze on 2017/7/5. */public interface IUserDao extends IBaseDao<User>{    User loadByUsername(String username);}

这个接口中什么方法也没有,因为公共方法已经写进IBaseDao中了,我们可以在这里面写User对象独有的方法,这儿继承IBaseDao需要指定具体实现类型。

编写UserDao.java

package org.yamikaze.dao.impl;import org.apache.ibatis.session.SqlSession;import org.yamikaze.model.User;import org.yamikaze.utils.SqlSessionUtil;import java.io.IOException;/** * Created by yamikaze on 2017/7/11. */public class UserDao extends BaseDao<User> implements  IUserDao{    public User loadByUsername(String username) {        SqlSession session = null;        try {            session = SqlSessionUtil.openSession();            return session.selectOne(getClz().getName()+".loadByUsername",username);        } catch(Exception e) {        } finally {            SqlSessionUtil.closeSession(session);        }        return null;    }}
因为公共方法的实现在BaseDao中实现了,所以我们只实现IUserDao中的方法
接下来做下测试吧!

package org.yamikaze.test;import org.yamikaze.dao.impl.IUserDao;import org.yamikaze.dao.impl.UserDao;import org.yamikaze.model.User;/** * Created by yamikaze on 2017/7/11. */public class UserDaoTest {    public static void main(String[] args) {        IUserDao userDao = new UserDao();        User u = new User();        u.setUsername("tom");        u.setSex("man");        u.setPassword("951001");        userDao.save(u);    }}
测试结果


成功了,让我们看看下一种使用方式吧!

    5.3、使用接口

              在5.2中使用的是类,Mybatis还提供了一种接口的使用方式。

     使用方式如下:

public static void insert() {        InputStream is = null;        SqlSessionFactory factory = null;        SqlSession session = null;        try {            is = Resources.getResourceAsStream("mybatis-config.xml");            factory = new SqlSessionFactoryBuilder().build(is);            session = factory.openSession();            IUserDao userDao = session.getMapper(IUserDao.class);            User user = new User();            user.setUsername("zs3");            user.setPassword("123");            user.setSex("man");            userDao.save(user);            session.commit();        } catch (IOException e) {            e.printStackTrace();        } finally {            if(session!=null) session.close();        }    }
可以看出与使用类的方式相差不大,但是不同的是我们调用的是借口里面的方法。

与使用类一致,也可以写一个IBaseDao来简化代码,这儿就不再赘述了。接口里面的方法要与配置文件中的id相对应,如果接口方法名不存在于配置文件中会报错。

这种方式可以有代码提示,即到底配置文件中有哪些sql语句(前提是保证接口中方法与配置文件中id一一对应)。

特别注意:session.getMapper(class类型)中的class类型

例如:IUserDao的全称限定名是org.yamikaze.dao.impl.IUserDao,那么userMapper配置文件中的命名空间就一定是这个字符串,否则会报错。

原创粉丝点击