mybatis学习一:基于xml与注解配置入门实例与问题

注:本case参考自:http://www.cnblogs.com/ysocean/p/7277545.html

一:Mybatis的介绍:                                         

  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
  • iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
  • MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。

二:基于xml配置的入门实例与介绍(idea的maven项目):                                            

1:case项目结构如图:(pom文件)

    

  几点注意:

    • 有可能idea下Maven项目会很卡,那么调整:Other Setting->default Setting->搜索maven->Runner中:VM Options设置为:-DarchetypeCatalog=internal;
    • main目录下的java使我们自己建的,要将java->右键->Mark Directory as设置为root(否则底下不能建立包文件);

  pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <!--
modelVersion:pom文件的模型版本
关于group id和artifact id,为了便于多人多模块协同开发管理(以后会讲),建议使用以下命名规范
group id:com.公司名.项目名
artifact id:功能模块名
packaging:项目打包的后缀,war是web项目发布用的,默认为jar
version:     artifact模块的版本
name和url:相当于项目描述,可删除
group id + artifact id +version :项目在仓库中的坐标
   -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.company.project</groupId>
    <artifactId>module</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>test Maven Webapp</name>
    <url>http://maven.apache.org</url>
  <!--上面这部分必须有-->

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <!--<dependency>这里的jdbc的数据库连接jar总是报错,可以注释掉后从外部导入jar
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.7-bin</version>
        </dependency>-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

2、创建数据库表:

 1 create database spring_mybatis_test1;
 2 use spring_mybatis_test1;
 3 create table user(
 4     id int(20) not null auto_increment,
 5     username varchar(50) ,
 6     sex varchar(10),
 7     birthday date,
 8     address varchar(100),
 9     primary key(id)
10 );

 向其中插入一条数据: insert into user(id,username,sex,birthday,address,) values(1,‘tom’,‘男’,'1993-05-25','earth'); 

补充:下面将要用到的配置参数:

  ①、parameterType:指定输入参数的类型

  ②、resultType:指定输出结果的类型,在select中如果查询结果是集合,那么也表示集合中每个元素的类型

  ③、#{}:表示占位符,用来接收输入参数,类型可以是简单类型,pojo,HashMap等等

    如果接收简单类型,#{}可以写成 value 或者其他名称

    如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值

  ④、${}:表示一个拼接符,会引起 sql 注入,不建议使用  

    用来接收输入参数,类型可以是简单类型,pojo,HashMap等等

    如果接收简单类型,${}里面只能是 value

    如果接收 pojo 对象值,通过 OGNL 读取对象中的属性值,即属性.属性.属性...的方式获取属性值

3:Mybatis的配置文件mybatis-configuration.xml:(事务,dataSource,userMapper.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>

    <!-- 注意:environments标签,当mybatis和spring整合之后,这个标签是不用配置的 -->

    <!-- 可以配置多个运行环境,但是每个 SqlSessionFactory 实例只能选择一个运行环境
      一、development:开发模式
       二、work:工作模式-->
    <environments default="development">
        <!--id属性必须和上面的default一样  -->
        <environment id="development">
            <!--事务管理器
                一、JDBC:这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围
                二、MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期
                    比如 spring 或 JEE 应用服务器的上下文,默认情况下,它会关闭连接。然而一些容器并不希望这样,
                    因此如果你需要从连接中停止它,就可以将 closeConnection 属性设置为 false,比如:
                    <transactionManager type="MANAGED">
                        <property name="closeConnection" value="false"/>
                    </transactionManager>
              -->
            <transactionManager type="JDBC"/>
            <!--dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象源  -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/spring_mybatis_test1"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- 注册userMapper.xml文件,
        userMapper.xml位于com.ys.mapper这个包下,所以resource写成com/ys/mapper/userMapper.xml-->
        <mapper resource="mapping/userMapping.xml"/>
    </mappers>
</configuration>

4:实体类和映射文件userMapper.xml

  • 实体类User:
     1 package com.spring.model;
     2 
     3 import java.util.Date;
     4 public class User {
     5     private int id;
     6     private String username;
     7     private String sex;
     8     private Date birthday;
     9     private String address;
    10     public int getId() {
    11         return id;
    12     }
    13     public void setId(int id) {
    14         this.id = id;
    15     }
    16     public String getUsername() {
    17         return username;
    18     }
    19     public void setUsername(String username) {
    20         this.username = username;
    21     }
    22     public String getSex() {
    23         return sex;
    24     }
    25     public void setSex(String sex) {
    26         this.sex = sex;
    27     }
    28     public Date getBirthday() {
    29         return birthday;
    30     }
    31     public void setBirthday(Date birthday) {
    32         this.birthday = birthday;
    33     }
    34     public String getAddress() {
    35         return address;
    36     }
    37     public void setAddress(String address) {
    38         this.address = address;
    39     }
    40     @Override
    41     public String toString() {
    42         return "User [id=" + id + ", username=" + username + ", sex=" + sex
    43                 + ", birthday=" + birthday + ", address=" + address + "]";
    44     }
    45 }
    View Code
  • 映射文件:注意36-49行的自增主键获取
     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE mapper
     3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     5 <mapper namespace="user"><!--注意namespace的名称,测试文件中直接引用namespace-->
     6 
     7     <!-- 根据 id 查询 user 表中的数据
     8         id:唯一标识符,此文件中的id值不能重复
     9         resultType:返回值类型,一条数据库记录也就对应实体类的一个对象
    10         parameterType:参数类型,也就是查询条件的类型
    11    -->
    12     <select id="selectUserById"
    13             resultType="com.spring.model.User" parameterType="int">
    14         <!-- 这里和普通的sql 查询语句差不多,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着 -->
    15         select * from user where id = #{id}
    16     </select>
    17 
    18     <!-- 查询 user 表的所有数据
    19         注意:因为是查询所有数据,所以返回的应该是一个集合,这个集合里面每个元素都是User类型
    20      -->
    21     <select id="selectUserAll" resultType="com.spring.model.User">
    22         select * from user
    23     </select>
    24 
    25     <!-- 模糊查询:根据 user 表的username字段
    26             下面两种写法都可以,但是要注意
    27             1、${value}里面必须要写value,不然会报错
    28             2、${}表示拼接 sql 字符串,将接收到的参数不加任何修饰拼接在sql语句中
    29             3、使用${}会造成 sql 注入
    30      -->
    31     <select id="selectLikeUserName" resultType="com.spring.model.User" parameterType="String">
    32         select * from user where username like '%${value}%'
    33         <!-- select * from user where username like #{username} -->
    34     </select>
    35 
    36     <!-- 向 user 表插入一条数据 -->
    37     <insert id="insertUser" parameterType="com.spring.model.User">
    38         <!-- 将插入的数据主键返回到 user 对象中
    39              keyProperty:将查询到的主键设置到parameterType 指定到对象的那个属性
    40              select LAST_INSERT_ID():查询上一次执行insert 操作返回的主键id值,只适用于自增主键
    41              resultType:指定 select LAST_INSERT_ID() 的结果类型
    42              order:AFTER,相对于 select LAST_INSERT_ID()操作的顺序
    43          -->
    44         <selectKey keyProperty="id" resultType="int" order="AFTER">
    45             select LAST_INSERT_ID()
    46         </selectKey>
    47         insert into user(username,sex,birthday,address)
    48         value(#{username},#{sex},#{birthday},#{address})
    49     </insert>
    50 
    51     <!-- 根据 id 更新 user 表的数据 -->
    52     <update id="updateUserById" parameterType="com.spring.model.User">
    53         update user set username=#{username} where id=#{id}
    54     </update>
    55 
    56     <!-- 根据 id 删除 user 表的数据 -->
    57     <delete id="deleteUserById" parameterType="int">
    58         delete from user where id=#{id}
    59     </delete>
    60 </mapper>
      

5:测试类:

  1 package com.ys.test;
  2  
  3 import java.io.InputStream;
  4 import java.util.List;
  5  
  6 import org.apache.ibatis.session.SqlSession;
  7 import org.apache.ibatis.session.SqlSessionFactory;
  8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  9 import org.junit.Before;
 10 import org.junit.Test;
 11  
 14 public class CRUDTest {
 15     //定义 SqlSession
 16     SqlSession session =null;
 17      
 18     @Before
 19     public void init(){
 20         //定义mybatis全局配置文件
 21         String resource = "mybatis-configuration.xml";
 22         //加载 mybatis 全局配置文件
 23         InputStream inputStream = CRUDTest.class.getClassLoader().getResourceAsStream(resource);
 25         //构建sqlSession的工厂
 26         SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
 27         //根据 sqlSessionFactory 产生 session
 28         session = sessionFactory.openSession();
 29     }
 30      
 31     //根据id查询user表数据
 32     @Test
 33     public void testSelectUserById(){
 34         /*这个字符串由 userMapper.xml 文件中 两个部分构成
 35             <mapper namespace="user"> 的 namespace 的值
 36             <select id="selectUserById" > id 值*/
 37         String statement = "user.selectUserById";
 38         User user = session.selectOne(statement, 1);
 39         System.out.println(user);
 40         session.close();
 41     }
 42      
 43     //查询所有user表所有数据
 44     @Test
 45     public void testSelectUserAll(){
 46         String statement = "user.selectUserAll";
 47         List<User> listUser = session.selectList(statement);
 48         for(User user : listUser){
 49             System.out.println(user);
 50         }
 51         session.close();
 52     }
 53      
 54     //模糊查询:根据 user 表的username字段
 55     @Test
 56     public void testSelectLikeUserName(){
 57         String statement = "user.selectLikeUserName";
 58         List<User> listUser = session.selectList(statement, "%t%");
 59         for(User user : listUser){
 60             System.out.println(user);
 61         }
 62         session.close();
 63          
 64     }
 65     //向 user 表中插入一条数据
 66     @Test
 67     public void testInsertUser(){
 68         String statement = "user.insertUser";
 69         User user = new User();
 70         user.setUsername("Bob");
 71         user.setSex("女");
 72         session.insert(statement, user);
 73         //提交插入的数据
 74         session.commit();
 75         session.close();
 76     }
 77      
 78     //根据 id 更新 user 表的数据
 79     @Test
 80     public void testUpdateUserById(){
 81         String statement = "user.updateUserById";
 82         //如果设置的 id不存在,那么数据库没有数据更改
 83         User user = new User();
 84         user.setId(4);
 85         user.setUsername("jim");
 86         session.update(statement, user);
 87         session.commit();
 88         session.close();
 89     }   
 91  
 92     //根据 id 删除 user 表的数据
 93     @Test
 94     public void testDeleteUserById(){
 95         String statement = "user.deleteUserById";
 96         session.delete(statement,4);
 97         session.commit();
 98         session.close();
 99     }
100 }

结果:以下我只测试了testSelectUserById和testSelectLikeUserName,两个是一样的: User [id=1, username=tom, sex=男, birthday=Tue May 25 00:00:00 CST 1993, address=earth] 。

6:获取主键值:

  • 数据库有自增主键:映射配置中的36-49行
     1 <!-- 向 user 表插入一条数据 -->
     2     <insert id="insertUser" parameterType="com.ys.po.User">
     3         <!-- 将插入的数据主键返回到 user 对象中
     4              keyProperty:将查询到的主键设置到parameterType 指定到对象的那个属性
     5              select LAST_INSERT_ID():查询上一次执行insert 操作返回的主键id值,只适用于自增主键
     6              resultType:指定 select LAST_INSERT_ID() 的结果类型
     7              order:AFTER,相对于 select LAST_INSERT_ID()操作的顺序
     8          -->
     9         <selectKey keyProperty="id" resultType="int" order="AFTER">
    10             select LAST_INSERT_ID()
    11         </selectKey>
    12         insert into user(username,sex,birthday,address)
    13             value(#{username},#{sex},#{birthday},#{address})
    14     </insert>
  • 非自增主键:
     1 <!-- 向 user 表插入一条数据 -->
     2     <insert id="insertUser" parameterType="com.ys.po.User">
     3         <!-- 将插入的数据主键返回到 user 对象中
     4         流程是:首先通过 select UUID()得到主键值,然后设置到 user 对象的id中,在进行 insert 操作
     5              keyProperty:将查询到的主键设置到parameterType 指定到对象的那个属性
     6              select UUID():得到主键的id值,注意这里是字符串
     7              resultType:指定 select UUID() 的结果类型
     8              order:BEFORE,相对于 select UUID()操作的顺序
     9          -->
    10         <selectKey keyProperty="id" resultType="String" order="BEFORE">
    11             select UUID()
    12         </selectKey>
    13         insert into user(id,username,sex,birthday,address)
    14             value(#{id},#{username},#{sex},#{birthday},#{address})
    15     </insert>

三:基于注解配置的入门实例与介绍(idea的maven项目):                              

1:我们直接在上面的case中配置注解方式,整个目录结构如下:   

  

需要改动的地方包括以上三个部分:

2:不需要动的部分       

  • pom.xml不需要改动;
  • User实体bean不需要改动;
  • userMapping.xml弃用

3、定义操作user表的注解接口UserMapper.java(接口)     

 1 package com.spring.model;
 2 
 3 import org.apache.ibatis.annotations.Delete;
 4 import org.apache.ibatis.annotations.Insert;
 5 import org.apache.ibatis.annotations.Select;
 6 import org.apache.ibatis.annotations.Update;
 7 
 8 public interface UserMapper {
 9 
10     //根据 id 查询 user 表数据
11     @Select("select * from user where id=#{id}")
12     public User selectUserById(int id) throws  Exception;
13 
14     //箱user插入一条数据
15     @Insert("insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})")
16     public void insertUser(User user) throws Exception;
17 
18     //根据 id 修改 user 表数据
19     @Update("update user set username=#{username},sex=#{sex} where id=#{id}")
20     public void updateUserById(User user) throws Exception;
21 
22     //根据 id 删除 user 表数据
23     @Delete("delete from user where id=#{id}")
24     public void deleteUserById(int id) throws Exception;
25 }

4、mybatis-configuration.xml中注册映射接口UserMapper.java   

1 ......
2 <mappers>
3     <!-- xml方式,注册userMapper.xml文件,
4     userMapper.xml位于com.ys.mapper这个包下,所以resource写成com/ys/mapper/userMapper.xml
5     <mapper resource="mapping/userMapping.xml"/>-->
6     <mapper class="com.spring.model.UserMapper"></mapper>
7 </mappers>

5、创建测试类  

 1 package com.spring;
 2 
 3 import com.spring.CRUDTest;
 4 import com.spring.model.User;
 5 import com.spring.model.UserMapper;
 6 import org.apache.ibatis.session.SqlSession;
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 9 import org.junit.Before;
10 import org.junit.Test;
11 
12 import java.io.InputStream;
13 
14 public class TestAnnotationCRUD {
15     SqlSession session=null;
16 
17     @Before
18     public void init(){
19         //定义mybatis全局配置文件
20         String resource = "mybatis-configuration.xml";
21         //加载 mybatis 全局配置文件
22         InputStream inputStream = CRUDTest.class.getClassLoader().getResourceAsStream(resource);
23         //构建sqlSession的工厂
24         SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
25         //根据 sqlSessionFactory 产生 session
26         session = sessionFactory.openSession();
27     }
28 
29     //注解的增删改查方法测试
30     @Test
31     public void testAnncationCRUD() throws Exception {
32         //根据session获取 UserMapper接口
33         UserMapper userMapper = session.getMapper(UserMapper.class);
34         //调用selectUserById()方法
35         User user = userMapper.selectUserById(1);
36         System.out.println(user);
37 
38         //调用  insertUser() 方法
39         User user1 = new User();
40         user1.setUsername("aliks");
41         user1.setSex("不详");
42         userMapper.insertUser(user1);
43 
44         //调用 updateUserById() 方法
45         User user2 = new User();
46         user2.setId(6);
47         user2.setUsername("lbj");
48         userMapper.updateUserById(user2);
49 
50         //调用 () 方法
51         userMapper.deleteUserById(6);
52 
53         session.commit();
54         session.close();
55     }
56 
57

idea输出: User [id=1, username=tom, sex=男, birthday=Tue May 25 00:00:00 CST 1993, address=earth] 

数据库结果:

注解配置使我们放弃了映射文件mapping.xml,需要接口实现数据库操作与到方法间的映射

  

  

  

  

 
原文地址:https://www.cnblogs.com/whtblog/p/9071806.html