博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Mybatis框架入门
阅读量:6489 次
发布时间:2019-06-24

本文共 45571 字,大约阅读时间需要 151 分钟。

Mybatis框架

一、什么是Mybatis  

  MyBatis 本是的一个开源项目, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
  MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
                                                                                      ---------------百度百科

二、Mybatis与Hibernate区别

  两个都是持久层框架,操作数据库,但是两者还是有区别的 

  hibernate:它是一个标准的orm框架,比较重量级,学习成本高.

  优点:高度封装,使用起来不用写sql,开发的时候,会减低开发周期.
  缺点:sql语句无法优化
  应用场景:oa(办公自动化系统), erp(企业的流程系统)等,还有一些政府项目,
  总的来说,在用于量不大,并发量小的时候使用.
  mybatis:它不是一个orm框架, 它是对jdbc的轻量级封装, 学习成本低,比较简单
  优点:学习成本低, sql语句可以优化, 执行效率高,速度快
  缺点:编码量较大,会拖慢开发周期
  应用场景: 互联网项目,比如电商,P2p等
  总的来说是用户量较大,并发高的项目。

三、体验原始的jdbc开发

  1、导入jar包

   此时操作数据库,需要引入数据库驱动,这里我使用的是mysql驱动

  

  2、编写jdbc程序

  

public static void main(String[] args) {        Connection connection = null;        PreparedStatement preparedStatement = null;        ResultSet resultSet = null;                try {            //加载数据库驱动            Class.forName("com.mysql.jdbc.Driver");                        //通过驱动管理类获取数据库链接            connection =  DriverManager.getConnection("jdbc:mysql://192.168.174.130:3306/SSM", "root", "root");            //定义sql语句 ?表示占位符        String sql = "select * from myUser where username = ?";            //获取预处理statement            preparedStatement = connection.prepareStatement(sql);            //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值            preparedStatement.setString(1, "王五");            //向数据库发出sql执行查询,查询出结果集            resultSet =  preparedStatement.executeQuery();            //遍历查询结果集            while(resultSet.next()){                System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));            }        } catch (Exception e) {            e.printStackTrace();        }finally{            //释放资源            if(resultSet!=null){                try {                    resultSet.close();                } catch (SQLException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if(preparedStatement!=null){                try {                    preparedStatement.close();                } catch (SQLException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if(connection!=null){                try {                    connection.close();                } catch (SQLException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    }

  缺点:频繁创建释放资源降低性能;代码耦合性强,不易维护;传参与所获结果集编码不够灵活(存在硬编码)

  综上:mybatis解决了以上问题

  1、SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接,大大减少了不断创建释放资源。

  2、Sql语句配置在XXXXmapper.xml文件中与java代码分离。

  3、Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。解决了条件查询中笨重问题

 

 

四、快速部署环境

  1、下载jar包

  mybatis官网:   

  jar包下载地址:  

  2、新建工程,导入相关jar包

  

  3、在工程(不是src)下建立一个源码包,用于存放配置文件

  4、在源码中配置一个日志文件,用于打印日志

# Global logging configurationlog4j.rootLogger=DEBUG, stdout# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

  5、配置核心配置文件

  配置文件中主要是配置连接数据库和事务管理的内容,文件名可以自定义,默认SqlMapConfig.xml

  6、配置sql映射文件,文件名自定义,这里默认为User.xml,

  与hibernate想区别的是:hibernate是通过操作映射文件对象来操作数据库,与sql无太大关系;mybatis的映射文件是用来写sql语句的

  注意:此文件放在源码包下

  7、在核心配置文件中引入映射文件

  

  此时环境差不多就部署好了

五、需求开发

  1、根据id查询一个客户

  1)建立客户表

  2)定义pojo类

package com.clj.pojo;import java.util.Date;import java.util.List;public class User {    private int id;    private String username;// 用户姓名    private String sex;// 性别    private Date birthday;// 生日    private String address;// 地址    private List
ordersList; public List
getOrdersList() { return ordersList; } public void setOrdersList(List
ordersList) { this.ordersList = ordersList; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }

  3)在User.xml文件中配置sql语句

  注意:当传入参数类型时原始型时,占位符中的括号中的值可以随意设置,但最好可读性较强(占位符能自动进行java类型和jdbc类型转换,可以有效防止sql注入。

  3)测试

  值得注意的是,这里调用sql的写法

  @Test    public void testFindUserById() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputStream=Resources.getResourceAsStream(resource);        //创建工厂        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);        //通过工厂创建会话        SqlSession openSession=factory.openSession();        //第一个参数:所调用的sql语句:namespace+‘.’+SqlID        //第二个参数:传入的参数        User user=openSession.selectOne("test.findUserById",1);        System.out.println(user);        openSession.close();    }

  这里调用的是selectOne方法,旨在查询一条指定的数据,如果用它查询多条数据,会报异常(查询多条要用selectList)

  

 

  2、根据用户名查询客户

  1)在User.xml文件中配置sql语句

  注意:当传入的参数是非引用型时,拼接符要用"value"(拼接符不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value)

     这里返回值为List集合,配置为该集合的泛型

  2)测试

  @Test    public void testFindUSerByUserName() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();        //List
list=openSession.selectList("test.findUserByUserName","%王%"); List
list=openSession.selectList("test.findUserByUserName","王"); System.out.println(list); openSession.close(); }

  3、插入数据

  1)配置sql

select LAST_INSERT_ID()
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})

  注意:这里添加selectKey实现将主键返回,因为是先插入数据,才能获得主键,所以其属性值order="AFTER"

  如果是uuid(随机字符串),属性值order="Before"

select uuid()
insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})

 

  2) 测试

  @Test    public void testInsertUser() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();        User user=new User();        user.setUsername("赵四");        user.setBirthday(new Date());        user.setSex("1");        user.setAddress("长沙市");        System.out.println("======"+user.getId());        openSession.insert("test.insertUser",user);        //提交事务(mybatis会自动提交事务,但是不知道何时手动提交事务)        openSession.commit();        System.out.println("========"+user.getId());        openSession.close();    }

  4、删除更新数据

  1)配置sql语句

delete from user where id=#{id}
update user set username=#{username} where id=#{id}

  2)测试

@Test    public void testDelUserById() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();        openSession.delete("test.delUserById",29);        openSession.commit();        openSession.close();    }    @Test    public void testUpdateUserById()throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();        User user=new User();        user.setId(28);        user.setUsername("佳先森");        openSession.update("test.updateUserById",user);        openSession.commit();        openSession.close();    }

   扩展:将连接数据库中的属性封装到数据库配置文件中

  1、在源码包中配置db.properties

jdbc.driver=com.mysql.jdbc.Driver\tjdbc.url=jdbc:mysql://192.168.174.130:3306/SSMjdbc.username=rootjdbc.password=root

  2、修改核心配置文件

六、mybatis支持别名

  在核心配置文件中第一个类的别名,后面可以直接引用别名,无需配置全路径

七、mybatis引入映射文件写法

  有两种写法:一种是单个引入,另一种是包扫描的方式

八、MyBatis之Dao层的开发方式

  MyBatis之Dao层的开发方式有两种:原始Dao开发和Mapper接口开发

  1、Dao开发方式一:原始Dao开发

    1)配置user.xml中的sql语句

  
  

    select * from user where username like '%${value}%'

   </select>

 

    2)定义接口和实现类

package com.clj.dao;import java.util.List;import com.clj.pojo.User;public interface UserDao {    public User findUserById(Integer id);    public List
findUserByUserName(String username);}
package com.clj.dao;import java.util.List;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import com.clj.pojo.User;public class UserDaoImpl implements UserDao{    private SqlSessionFactory sqlSessionFactory;    //通过构造方法注入    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {        super();        this.sqlSessionFactory = sqlSessionFactory;    }    @Override    public User findUserById(Integer id) {        //SqlSession是线程不安全的,所以他的最佳使用的范围在方法体内        SqlSession opeanSession=sqlSessionFactory.openSession();        User user=opeanSession.selectOne("test.findUserById",id);        return user;    }    @Override    public List
findUserByUserName(String username) { SqlSession opeanSession=sqlSessionFactory.openSession(); List
list=opeanSession.selectList("test.findUserByUserName",username); return list; } }

  3)在核心配置文件SqlMapConfig.xml中引入user.xml

    

  4)定义测试类进行测试

package com.clj.Test;import java.io.InputStream;import java.util.List;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.Before;import org.junit.Test;import com.clj.dao.UserDao;import com.clj.dao.UserDaoImpl;import com.clj.pojo.User;public class UserDaoTest {    private SqlSessionFactory factory;        //@Before作用在测试方法之前执行这个方法    @Before    public void setUp() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();    }    @Test    public void testFindUserById() throws Exception{        //将初始化的工厂注入到实现类中        UserDao userDao=new UserDaoImpl(factory);        User user=userDao.findUserById(1);        System.out.println(user);    }    @Test    public void testFindUserByUserName() throws Exception{        UserDao userDao=new UserDaoImpl(factory);        List
list=userDao.findUserByUserName("王"); System.out.println(list); }}

  总结:原始Dao还是存在一些不好的因素:1.代码有重复 2.sqlSession调用sql时需要指定id值,存在硬编码

  2、Dao开发方式二:Mapper动态代理的方式

  Mapper动态代理的方式需要严格遵守一些规范

  需求一:通过主键查找用户;通过用户名查找用户;插入用户数据

 

  1)定义接口

package com.clj.UserMapper;import java.util.List;import com.clj.pojo.CustomerOrders;import com.clj.pojo.Orders;import com.clj.pojo.QueryVo;import com.clj.pojo.User;//与之关乎的配置文件要在同一个目录包下public interface UserMapper {    public User findUserById(Integer id);    //注意:这里是模糊查询,配置文件虽然写的是User,实际返回的是List集合    //动态代理形式中,如果返回结果集List,那么mybatis会在生成实现类的时候会自动调用selectList方法    public List
findUserByUserName(String userName); public void insertUser(User user); }

 

  2)定义其映射文件,最好是在同目录下

select LAST_INSERT_ID()
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})

 

   两文件的目录关系

   

 

  3)在核心配置文件中引入Mapper的配置文件

  ·4)测试类

  

package com.clj.Test;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.Date;import java.util.List;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.Before;import org.junit.Test;import com.clj.UserMapper.UserMapper;import com.clj.pojo.CustomerOrders;import com.clj.pojo.Orders;import com.clj.pojo.QueryVo;import com.clj.pojo.User;public class UserMapperTest {private static SqlSessionFactory factory;        //@Before作用在测试方法之前执行这个方法    @Before    public void setUp() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();    }    @Test    public void testFindUserById() throws Exception{        SqlSession openSession=factory.openSession();        //通过getMapper方法实列化接口        UserMapper mapper=openSession.getMapper(UserMapper.class);        User user=mapper.findUserById(1);        System.out.println(user);    } }

   另外:删除用户和更新用户sql配置文件方式为,具体步骤如上

delete from user where id=#{id}
update user set username=#{username} where id=#{id}

  需求二:根据用户名查询,利用高级查询Vo类

  1)创建Vo类封装用户属性,并提供set/get方法

package com.clj.pojo;import java.util.List;//用于高级查询public class QueryVo {    private User user;    private List
ids; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public List
getIds() { return ids; } public void setIds(List
ids) { this.ids = ids; } }

  2)在UserMapper.xml文件中配置查询语句

  3)定义接口

public List
findUserbyVo(QueryVo vo);

  4)测试类

public class UserMapperTest {private static SqlSessionFactory factory;        //@Before作用在测试方法之前执行这个方法    @Before    public void setUp() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();    }  @Test    public void testFindUserByVo() throws Exception{        SqlSession openSession=factory.openSession();        //通过getMapper方法实列化接口        UserMapper mapper=openSession.getMapper(UserMapper.class);        QueryVo vo=new QueryVo();        User user=new User();        user.setUsername("张");        user.setSex("1");         vo.setUser(user);        List
list=mapper.findUserbyVo(vo); System.out.println(list); openSession.close(); }}

  需求三:查询数据总数,利用count(*)

  1) 配置sql

  2) 配置接口

public Integer findUserCount();

  3)测试

@Test    public void testFindUserCount()throws Exception{        SqlSession opneSession=factory.openSession();        //通过getMapper方法实例化接口        UserMapper mapper=opneSession.getMapper(UserMapper.class);        Integer count=mapper.findUserCount();        System.out.println("===="+count);    }

  需求四:动态增加查询条件

  1)配置sql

  方式一:局部配置

  方式二:全局配置

and username like '%${username}%'
and sex=#{sex}

  2)接口

public List
findUserByUserNameAndSex(User user);

  3)测试

@Test    public void testFindUserbyUserNameAndSex() throws Exception{        SqlSession opneSession=factory.openSession();        UserMapper mapper=opneSession.getMapper(UserMapper.class);        User user=new User();        user.setUsername("张");        user.setSex("1");        List
list=mapper.findUserByUserNameAndSex(user); System.out.println(list); }

  需求五:查询主键在某个范围内(动态添加条件查询之foreach标签)

  1)sql配置文件

  2)接口

public List
findUserByIds(QueryVo vo);

  3)测试

public class UserMapperTest {private static SqlSessionFactory factory;        //@Before作用在测试方法之前执行这个方法    @Before    public void setUp() throws Exception{        String resource="SqlMapConfig.xml";        InputStream inputstream=Resources.getResourceAsStream(resource);        factory=new SqlSessionFactoryBuilder().build(inputstream);        SqlSession openSession=factory.openSession();    }@Test    public void testFindUserbyIds() throws Exception{        SqlSession opneSession=factory.openSession();        UserMapper mapper=opneSession.getMapper(UserMapper.class);        QueryVo vo=new QueryVo();        List
ids=new ArrayList
(); ids.add(1); ids.add(16); ids.add(28); ids.add(22); List
list=mapper.findUserByIds(vo);System.out.println(list); }}

  需求六:关联查询之一对一查询

  环境:一个客户对应多个订单,而一个订单对应一个客户

  方法一:使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息

  1)预测sql语句写法:SELECT orders.*,user.username,userss.address FROM orders,user WHERE orders.user_id = user.id

  2)定义订单类

package com.clj.pojo;import java.util.Date;public class Orders {     private Integer id;        private Integer userId;        private String number;        private Date createtime;        private String note;        public Integer getId() {            return id;        }        public void setId(Integer id) {            this.id = id;        }        public Integer getUserId() {            return userId;        }        public void setUserId(Integer userId) {            this.userId = userId;        }        public String getNumber() {            return number;        }        public void setNumber(String number) {            this.number = number == null ? null : number.trim();        }        public Date getCreatetime() {            return createtime;        }        public void setCreatetime(Date createtime) {            this.createtime = createtime;        }        public String getNote() {            return note;        }        public void setNote(String note) {            this.note = note == null ? null : note.trim();        }}

  3)定义封装客户和订单的pojo类,此类包含上边预测的sql语句字段

package com.clj.pojo;import java.util.Date;//一对一:select a.*,b.id uid,username,birthday,sex,address//from order a,user b//where a.user_id=b.id//注意:不能用实体User代替他属性//缺点:java是单继承public class CustomerOrders extends Orders{    private int uid;    private String username;// 用户姓名    private String sex;// 性别    private Date birthday;// 生日    private String address;// 地址    public int getUid() {        return uid;    }    public void setUid(int uid) {        this.uid = uid;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    public Date getBirthday() {        return birthday;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    }

    注意:OrdersCustom类继承Orders类后OrdersCustom类包括了Orders类的所有字段,只需要定义用户的信息字段即可。(注意:这里不能用user来取代这些属性)

  4)配置sql语句

  1)在order类中定义user属性

package com.clj.pojo;import java.util.Date;public class Orders {     private Integer id;        private Integer userId;        private String number;        private Date createtime;        private String note;                private User user;                public User getUser() {            return user;        }        public void setUser(User user) {            this.user = user;        }        public Integer getId() {            return id;        }        public void setId(Integer id) {            this.id = id;        }        public Integer getUserId() {            return userId;        }        public void setUserId(Integer userId) {            this.userId = userId;        }        public String getNumber() {            return number;        }        public void setNumber(String number) {            this.number = number == null ? null : number.trim();        }        public Date getCreatetime() {            return createtime;        }        public void setCreatetime(Date createtime) {            this.createtime = createtime;        }        public String getNote() {            return note;        }        public void setNote(String note) {            this.note = note == null ? null : note.trim();        }}

  2)配置sql语句

  

  5)配置接口

public List
findOrderAndUser1();

  6)定义测试类

@Test    public void testFindORdersAndUser() throws Exception{        SqlSession opneSession=factory.openSession();        UserMapper mapper=opneSession.getMapper(UserMapper.class);        List
list=mapper.findOrderAndUser1(); System.out.println(list); }

  总结:此方法虽然简单,定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。但是缺点是pojo类只能单继承

  方式二:使用resultMap,定义专门的resultMap用于映射一对一查询结果

  1)配置sql    注意此时不需要CustomerOrders 类

       
       

  2)配置接口

public List
findOrderAndUser2();

  3)测试类

  @Test    public void findOrderAndUser2() throws Exception{        SqlSession opneSession=factory.openSession();        UserMapper mapper=opneSession.getMapper(UserMapper.class);        List
list=mapper.findOrderAndUser2(); for(Orders order:list){ System.out.println(order.getUserId()+"\t"+order.getCreatetime()); } }

  需求七:一对多查询

  1)预测sql语句

  SELECT u.*, o.id oid,o.number,o.createtime,o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id

  2)在user pojo类中加上List集合属性

package com.clj.pojo;import java.util.Date;import java.util.List;public class User {    private int id;    private String username;// 用户姓名    private String sex;// 性别    private Date birthday;// 生日    private String address;// 地址    private List
ordersList; public List
getOrdersList() { return ordersList; } public void setOrdersList(List
ordersList) { this.ordersList = ordersList; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }

  3)配置sql

  

  4)定义接口

public List
findUserAndOrders();

  5)测试类

     @Test        public void findUserAndOrders() throws Exception{            SqlSession opneSession=factory.openSession();            UserMapper mapper=opneSession.getMapper(UserMapper.class);            List
list=mapper.findUserAndOrders(); System.out.println(list); }

九、Mybatis与Spring整合

  1、整合思路  

  SqlSessionFactory对象应该放到spring容器中作为单例存在。

  传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
  Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
  数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

  2、环境部署

  1)导入所需jar包

   在导入spring包和mybaits包之外还要jar两者的整合包

  

     

         至于maven构建项目,其pom文件的约束为:

         注意:至于jdbc可以用c3p0,也可以用dbcp,但是无论这两个都需要用到spring-jdbc的jar包,否则会报错误

Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121)    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1570)    ... 41 more
org.springframework
spring-jdbc
4.3.17.RELEASE
org.mybatis
mybatis
3.4.5
commons-logging
commons-logging
1.2
log4j
log4j
1.2.17
mysql
mysql-connector-java
5.0.8
org.mybatis
mybatis-spring
1.3.1
org.springframework
spring-beans
4.3.17.RELEASE
org.springframework
spring-context
4.3.17.RELEASE
org.springframework
spring-core
4.3.17.RELEASE
org.springframework
spring-expression
4.3.17.RELEASE
aopalliance
aopalliance
1.0
org.aspectj
aspectjweaver
1.7.4
org.springframework
spring-aspects
4.3.17.RELEASE
org.springframework
spring-tx
4.3.17.RELEASE
junit
junit
4.12
test
org.springframework
spring-test
4.3.17.RELEASE
test
c3p0
c3p0
0.9.1.2

  2)在工程项目下(非src)创建一个源码包,用来存放配置文件

   配置连接数据库驱动配置文件db.properties

jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://192.168.174.130:3306/SSMjdbc.username=rootjdbc.password=root

  1))配置日志配置文件log4j.properties

### direct log messages to stdout ###

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=info, stdout

  配置spring的配置文件applicationContext.xml

  1)))配置数据库驱动,加载db.properties文件

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

  <property name="driverClass" value="${jdbc.driver}"/>
  <property name="jdbcUrl" value="${jdbc.url}"/>
  <property name="user" value="${jdbc.password}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>

  2)))将sqlSessionfactory的创建交给spring管理

  全部代码如下

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

      <property name="driverClass" value="${jdbc.driver}"/>
      <property name="jdbcUrl" value="${jdbc.url}"/>
      <property name="user" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </bean>

  其中org.mybatis.spring.SqlSessionFactoryBean的路径配置如下图

  

  2)) 配置mybatis数据sql映射文件

  3、整合之Dao层的开发

   1)开发方式一之传统dao开发

    1))思路:

     想为接口+实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类

     2))接口定义和javaBean

     这里定义了根据id查询和根据用户名查询两个方法package com.clj.dao;

import java.util.List;import com.clj.pojo.User;public interface UserDao {    public User findUserById(Integer id);    public List
findUserByUserName(String username);

    public List<UserBean> findUserByUserNameAndMoney(UserBean userBean);

    public List<UserBean> findUserById(QueryVo vo);

}
@Componentpublic class UserBean {    private Integer id;    private String username;    private String age;    private Integer money;        //set/get方法    }
@Componentpublic class QueryVo {    private List
ids;}

     3))实现类定义

     实现类实现SqlSessionDaoSupport

package com.clj.dao;import java.util.List;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.support.SqlSessionDaoSupport;import com.clj.pojo.User;//此时dao层要继承SqlSessionDaoSupportpublic class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{    @Override    public User findUserById(Integer id) {        //SqlSession是线程不安全的,所以他的最佳使用的范围在方法体内        SqlSession opeanSession=this.getSqlSession();        User user=opeanSession.selectOne("test.findUserById",id);        //opeanSession.close();        return user;            }    @Override    public List
findUserByUserName(String username) { SqlSession opeanSession=this.getSqlSession(); List
list=opeanSession.selectList("test.findUserByUserName",username); return list; }

    public List<UserBean> findUserByUserNameAndMoney(UserBean userBean) {

      SqlSession sqlSession=this.getSqlSession();
      List<UserBean> user=sqlSession.selectList("test.findUserByUserNameAndMoney",userBean);
      return user;
    }

 

    @Override

    public List<UserBean> findUserById(QueryVo vo) {
      SqlSession sqlSession=this.getSqlSession();
      List<UserBean> user=sqlSession.selectList("test.findUserById",vo);
      return user;
    }

}

     4)) 注入dao层于sprign配置文件(applicationContext.xml)

     这里为dao层注入了sqlSessionFactory

 

     5))SqlMap.xml

   6))User.xml

and username like '%${username}%'
and age> #{age}

    6)) 测试类

    方式一:

package com.clj.Test;import org.junit.Before;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.clj.dao.UserDao;import com.clj.pojo.User;public class UserDaoTest {    private ApplicationContext applicationContext;    @Before    public void setUp() throws Exception{        //这里可加classpath,也可不加        String configLocation="classpath:applicationContext.xml";        applicationContext=new ClassPathXmlApplicationContext(configLocation);    }    @Test    public void testFindUserById() throws Exception{        //获取UserDao对象,getBean中的字符串是在applcationContext.xml中神明的         UserDao userDao=(UserDao)applicationContext.getBean("userDao");        User user=userDao.findUserById(1);        System.out.println(user);    }}

  方式二:

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:ApplicationContext.xml")public class TestDemo1 {    @Resource    private ApplicationContext application;    @Resource    private UserBean userBean;    @Resource    private UserDao userDao;    @Resource    private QueryVo vo;    @Test    public void run2(){        userDao=(UserDao) application.getBean("userDao");        userBean.setUsername("李");        userBean.setAge("11");        List
list=userDao.findUserByUserNameAndMoney(userBean); System.out.println(list); } @Test public void run3(){ userDao=(UserDao) application.getBean("userDao"); List
list=new ArrayList(); list.add(1); list.add(3); list.add(6); vo.setIds(list); List
temp=userDao.findUserById(vo); System.out.println(temp); }}

  注意:这里由于sqlSessionFactory归spring管理,所以其关闭也是有spring管理,如果在测试中手动关闭session,会报错

  

  2)开发方式二:Mapper代理形式开发dao

  1))新建一个mapper包,用来配置mapper的接口和配置文件

  mapper接口:这里和整合前mybatis中动态mapper代理接口代码一致

package com.clj.UserMapper;import java.util.List;import com.clj.pojo.CustomerOrders;import com.clj.pojo.Orders;import com.clj.pojo.QueryVo;import com.clj.pojo.User;//与之关乎的配置文件要在同一个目录包下public interface UserMapper {    public User findUserById(Integer id);    //注意:这里是模糊查询,配置文件虽然写的是User,实际返回的是List集合    //动态代理形式中,如果返回结果集List,那么mybatis会在生成实现类的时候会自动调用selectList方法    public List
findUserByUserName(String userName); public void insertUser(User user); public List
findUserbyVo(QueryVo vo); public Integer findUserCount(); public List
findUserByUserNameAndSex(User user); public List
findUserByIds(QueryVo vo); public List
findOrderAndUser1(); public List
findOrderAndUser2(); public List
findUserAndOrders();}

     2))配置sql映射文件:这里和整合前mybatis中动态mapper代理接口代码一致

and username like '%${username}%'
and sex=#{sex}
select LAST_INSERT_ID()
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
delete from user where id=#{id}
update user set username=#{username} where id=#{id}

    3))在applicationContext.xml映射文件中注入mapper接口

     方式一:手动配置

配置Mapper接口的全路径名称,其中property name="mapperInterface"是根据主类来配置的
public class MapperFactoryBean
extends SqlSessionDaoSupport implements FactoryBean
{ private Class
mapperInterface;}

  其中MapperScannerConfigurer的路径为

  

    方式二:采用包扫描的方式

     其中MapperScannerConfigurer的路径为

  

    如果采用包扫描的方式,他与mybatis中的sqlMapConfig.xml文件中扫描有冲突,需要屏蔽sqlMapConfig.xml的代码

  

 

    4))测试类

package com.clj.Test;import org.junit.Before;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.clj.UserMapper.UserMapper;import com.clj.pojo.User;public class UserMapperTest {    private ApplicationContext applicationContext;    @Before    public void setUp() throws Exception{        //这里可加classpath,也可不加        String configLocation="classpath:applicationContext.xml";        applicationContext=new ClassPathXmlApplicationContext(configLocation);    }    @Test    public void testFindUserById()throws Exception{
     //方式一:手动配置:通过bean中id获取 UserMapper userMapper=(UserMapper) applicationContext.getBean("userMapper");      //方式二:扫描方式:通过mapper接口名进行获取,注意,getBean()中的值是通过类名第一个字母小写得到 User user=userMapper.findUserById(1); System.out.println(user); }}

 十、MyBatis之逆向工程

  1、逆向工程作用

  自动生成Pojo类,还可以自动生成Mapper接口和映射文件,注意:生成的方式是追加而不是覆盖,所以不可以重复生成,重复生成的文件有问题,如果想重复生成将原来生 成的文件删除

  2、快速部署环境

   1)下载核心jar包mybatis-generator-core-1.3.2

   

  2)在项目工程(非src下)构建源码包,用来存放配置文件

  3)创建log4j.properties文件(只是打印日志,可以不配置)

# Global logging configurationlog4j.rootLogger=DEBUG, stdout# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

  4)配置generatorConfig.xml文件

   此文件用来配置Mapper中的信息(注意几点:1. 添加要生成的数据库表 2.pojo文件所在包路径 3.mapper文件所在包路径)

  5)根据指定的路径创建文件包

    这里要创建cn.clj.mapper与cn.clj.pojo包,逆向工程不会自动帮你键包,所有要提前创建

  

   6)创建启动类

    注意:这里的要配置generatorConfig.xml文件位置

package com.clj.Test;import java.io.File;import java.util.ArrayList;import java.util.List;import org.mybatis.generator.api.MyBatisGenerator;import org.mybatis.generator.config.Configuration;import org.mybatis.generator.config.xml.ConfigurationParser;import org.mybatis.generator.internal.DefaultShellCallback;public class StartService {    public void generator() throws Exception{        List
warnings = new ArrayList
(); boolean overwrite = true; File configFile = new File("config/generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { StartService startService = new StartService(); startService.generator(); } catch (Exception e) { e.printStackTrace(); }}}

 

 

 

 

 

 

 

 

 

 

  

 

转载于:https://www.cnblogs.com/cailijia52o/p/8725850.html

你可能感兴趣的文章
学习angularjs的内置API函数
查看>>
4、输出名称 Exported names
查看>>
Pre-echo(预回声),瞬态信号检测与TNS
查看>>
【转载】如何发送和接收 Windows Phone 的 Raw 通知
查看>>
poj2378
查看>>
Java文件清单列表
查看>>
[LeetCode] Reverse String 翻转字符串
查看>>
学习iOS【3】数组、词典和集合
查看>>
Hessian 原理分析--转
查看>>
转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端
查看>>
easyui传入map的数据前台展示出tree格式数据
查看>>
悲观的思考,乐观的生活.我们既需要思考的深度,也需要生活的温度!
查看>>
Vitamio中文API文档(4)—— VitamioInstaller
查看>>
yii框架常用url地址
查看>>
python3.4学习笔记(十六) windows下面安装easy_install和pip教程
查看>>
MyGUI 解析
查看>>
Linux中的ls命令详细使用
查看>>
graph-tool文档(一)- 快速开始使用Graph-tool - 2.属性映射、图的IO和Price网络
查看>>
GraphicsLab Project之辉光(Glare,Glow)效果 【转】
查看>>
Linux Curl命令
查看>>