Mybatis入门

Mybatis入门

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

Mybatis基本配置

pom.xml

若不用maven构建项目可以直接导入jar包:mybatis-x.x.x.jar。

使用Maven:需将下面的dependency 代码置于 pom.xml 文件中:

<dependency>
  <groupId>
org.mybatis</groupId>
  <artifactId>
mybatis</artifactId>
  <version>
3.3.0</version>
</dependency>

 

Configuration.xml

<configuration>

  <!--配置包的别名-->
  <typeAliases>
    <typeAlias alias="my.Student" type="com.seu.sun.model.Student"/>
    <!--<package name="com.seu.sun.model"/>--><!--也可以这样写包名-->
  </typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC">
        <property name="" value=""/>
      </transactionManager>
      <dataSource type="UNPOOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="0000"/>
      </dataSource>
    </environment>
  </environments>

  <!--配置一个包含完整类路径的xml文件-->
  <mappers>
    <mapper resource="com/seu/sun/mybatisConfig/mapper/Student.xml"/>
  </mappers>

</configuration>

<settings>

<setting name=”mapUnerscoreToCamelCasevalue=”true””>

<settings>

该设置将数据库中下划线命名(user_name)映射到Java驼峰命名(userName)。

Student.xml

<!DOCTYPE mapper
        PUBLIC "-//com.seu.sun.mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--对应接口的包名接口名(无需实现)使用接口的用法-->
<mapper namespace="com.seu.sun.mybatisConfig.mapper.StudentMapper">

    <resultMap type="my.Student" id="StudentsResult">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
        <result column="hobby" jdbcType="VARCHAR" property="hobby"/>
    </resultMap>

    <select id="selectAll" resultMap="StudentsResult">
        SELECT id,name,age,hobby FROM students
    </select>
    <select id="selectById" resultMap="StudentsResult">
        SELECT id,name,age,hobby FROM students WHERE id=#{id}
    </select>

    <insert id="insert">
        INSERT INTO students(name,age,hobby)
          VALUES (#{name},#{age},#{hobby})
    </insert>

    <update id="updateById">
        UPDATE students SET name = #{name},age=#{age} WHERE id=#{id}
    </update>

    <delete id="deleteById">
        DELETE FROM students WHERE id=#{id}
    </delete>
    
</mapper>

result标签

       可以不配置resultMap,直接配置resultType

<result>标签用于配置结果映射的方法,id为唯一标识,select标签填的resultMap即为该id,type为用于配置查询列所映射到的Java对象类型。extends选填,可以配置当前resultMap继承自其它resultMap,autoMapping选填,true或false,是否使用非映射字段(没有在resultMap中配置的字段)的自动映射功能。

该标签包括以下子标签:

<constructor>配置使用构造方法注入结果

<id>一个id结果,代表主键,<result>注入到java对象属性的普通结果。这两个标签包含以下属性:column数据库中得到的列名或列的别名,property映射到列结果的属性,javaType一个java类的完全限定名或别名(typeAlias配置),jdbcType列对应的数据库类型,typeHandler可以覆盖默认类型处理器。

<association>一个复杂的类型关联,许多结果将包装成这种类型

<collection>复杂类型的集合,实现一对多

<discriminator>根据结果值来决定使用哪个结果映射

<case>

select标签

<select>标签,id为命名空间中唯一标识符,可用来代表这条语句。resultMap为返回值的类型和映射关系,也可以配置resultType为java的某个类型。查询语句中#{id}是预编译参数的一种方式。

insert标签

<insert>标签,id同上。flushCache默认为true,任何时候只要语句被调用都会清空一级和二级缓存。timeout设置在抛出异常前,驱动程序等待数据库返回请求结果的秒数。statementType有STATEMENT、PREPARED、CALLABLE会分别使用Statement、PreparedStatement、CallableStatement,默认PREPARED。useGeneratedKeys默认false,设置true,Mybatis会使用JDBC的getGeneratedKeys方法来取出数据库内部生成的主键。KeyProperty获取主键值后将要赋值的属性名。对于指定的类型可以使用如:#{para,jdbcType=DATE}。

也可以使用子标签<selectKey>获取回写主键。

update标签

用法和insert比较类似。

delete标签

       用法和insert比较类似。

DBAccess.java

XML 中构建 SqlSessionFactory

用于连接数据库,获得sqlSession会话

/**
 * 访问数据库类
 */
public class DBAccess {
   public SqlSession getSqlSession() throws IOException {
      // 通过配置文件获取数据库连接信息
      Reader reader = Resources.getResourceAsReader("com/seu/sun/mybatisConfig/Configuration.xml");
      // 通过配置信息构建一个SqlSessionFactory
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
      // 通过sqlSessionFactory打开一个数据库会话
      SqlSession sqlSession = sqlSessionFactory.openSession();
      return sqlSession;
   }
}

 

纯XML实现方法

testCRUD.java

编写增删改查的各个方法,对应Student.xml文件中映射的方法。

/**
 * 实现方法有XML和接口方法
 */
public class testCRUD {
    private static SqlSession sqlSession;
    public static void main(String[] args) throws IOException {
        DBAccess dbAccess = new DBAccess();
        sqlSession=dbAccess.getSqlSession();
//        testSelect();
//        testSelectById();
//        testInsert();
//        testUpdateById();
//        testDeleteById();
        useInterface();
        sqlSession.close();
    }
    /**
     * 增删改查操作
     * 传入的类型参数可以为基本类型(一个),JavaBean(一个)
     * 当参数为多个时,可以使用Map(需要自己建立对应Key-Value)
     *也可以使用@Param注解(接口的方法,下面介绍)
     * */

    public static void testSelect(){
        List<Student> list = new ArrayList<>();
       //若冲突需要些写mappernamespace
        list=sqlSession.selectList("selectAll");
        for(Student s:list){
            System.out.println(s.getName()+s.getHobby());
        }
    }

    public static void testSelectById(){
//        Student s = new Student();
//        s.setId(6);//也可以传入Student对象,可以自动识别
        Student s = sqlSession.selectOne("selectById",1);
        System.out.println(s.getName()+s.getHobby());
    }

    public static void testInsert(){
        Student s = new Student();
        s.setAge(10);s.setHobby("跳舞");s.setName("小王");
        sqlSession.insert("insert",s);
        sqlSession.commit();
    }

    public static void testUpdateById(){
        Student s = new Student();
        s.setId(9);
        s.setAge(99);s.setHobby("没有");s.setName("小小");
        //可以通过map对参数直接赋值
//        Map<String,Object> map = new HashMap<>();
//        map.put("name","xiaohua");map.put("id",9);map.put("age",20);
        sqlSession.update("updateById");
        sqlSession.commit();
    }

    public static void testDeleteById(){
        sqlSession.delete("deleteById",10);
        sqlSession.commit();
    }

 

接口配合XML实现

接口可以配合XML使用,也可以配合注解来使用。XML可以单独使用,注解必须在接口中使用。

写对应的接口,方法名即为student.xml中对应的方法id,返回类型必须和XML中配置的resultType或resultMap中type类型一致。

StudentMapper.java

接口和XML是通过将namespace的值设置为接口的全限定名称来进行关联的(当只使用XML不用接口时,namespace可以设置为任意不重复的名称)。

将接口中方法和XML中定义的SQL语句(标签中id的值等于方法名)关联到一起。接口方法是可以重载的,但XML中id不能重复,接口中所有同名方法会对应XML中同一个id的方法。最常见的用法就是同名方法的其中一个增加RowBound类型参数用于实现分页查询。

传入的类型参数可以为基本类型(一个),JavaBean(一个),当参数为多个时,可以使用Map(需要自己建立对应Key-Value)也可以使用@Param注解。给参数配置@Param注解后,MyBatis就会自动将参数封装成Map类型,将方法参数和SQL语句中预编译参数进行映射。

Mapper接口没有实现类直接被调用是因为MyBatis使用了动态代理技术。

/**
 * 参数直接写在方法声明中,多个参数用@Param注解
 */
public interface StudentMapper {
    List<Student> selectAll();
    Student selectById(int id);
    int insert(Student student);
    int updateById(@Param("id")int id,@Param("name")String name,@Param("age")int age);
    int deleteById(int id);
}

 

testCRUD.java

public static void useInterface(){
    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
    studentMapper.selectAll();
    studentMapper.selectById(1);
    Student s = new Student();
    s.setId(3);
    s.setName("小花");
    s.setHobby("待定");
    s.setAge(13);
    studentMapper.insert(s);
    studentMapper.deleteById(11);
    studentMapper.updateById(9,"呵呵",18);
    sqlSession.commit();
}

 

注解方式基本用法

Mybatis注解就是将SQL语句直接写在接口上。

优点:开发效率高

缺点:修改SQL都需要重新编译

student2.xml

<!--对应接口的包名+接口名(无需实现)-->
<mapper namespace="com.seu.sun.mybatisConfig.mapper.Student2Mapper">

    <resultMap type="my.Student" id="StudentsResult">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
        <result column="hobby" jdbcType="VARCHAR" property="hobby"/>
    </resultMap>

</mapper>

 

Student2Mapper.java

public interface Student2Mapper {
    @Select({"select id,name,age,hobby",
             "from students",
             "where id=#{id}"})
    Student selectById(int id);
    @Select("select id,name,age,hobby from students")
    List<Student> selectAll();
    @Insert("insert students (name,age,hobby) VALUES (#{name},#{age},#{hobby})")
    int insert(Student student);
    @Update("UPDATE students SET name = #{name},age=#{age} WHERE id=#{id}")
    int updateById(@Param("id")int id, @Param("name")String name, @Param("age")int age);
    @Delete("DELETE FROM students WHERE id=#{id}")
    int deleteById(int id);
}
@Result注解

如:

@Results({
       
@Result(property = "id",column = "id",id = true),
       
@Result(property = "name",column = "name"),
       
@Result(property = "age",column = "age"),
       
@Result(property = "hobby",column = "hobby")
})

 

@Select注解

参数可以是字符串数组类型也可以是字符串类型。如上面的例子。

@Insert注解

       该注解本身比较简单,但需要返回主键的值会稍微复杂。使用@Options(useGeneratedKeys=true,keyProperty = “id”)来设置这两个属性。若返回非自增主键,使用@SelectKey注解。

@Update注解和@Delete注解

使用方法较为简单,例子见上面。

@Provider注解

MyBatis还提供了4种Provider注解,分别是@SelectProvider、@InsertProvider、@UpdateProvider和#DeleteProvider实现增删改查的功能。

testCRUD.java

public static void useInterface2(){
    Student2Mapper student2Mapper = sqlSession.getMapper(Student2Mapper.class);
    Student s = student2Mapper.selectById(1);
    System.out.println(s.getName());

    for(Student stu:student2Mapper.selectAll()){
        System.out.println(stu.getId()+stu.getName());
    }
    s.setAge(100);s.setId(9);
    student2Mapper.insert(s);
    student2Mapper.deleteById(14);

    sqlSession.commit();
}

 

Mybatis动态SQL

if用法

在where语句中判断是否使用某个查询条件,if标签有一个必填属性test,判断条件property!=null适用于任何类型字段,而property!=’’仅适用于String类型字段,判断是否为空字符串。如:

<select id="selectAll" resultMap="StudentsResult">
    SELECT id,name,age,hobby FROM students
    WHERE 1=1
    <if test="name !=null and name != '' ">
            AND name LIKE concat('%',#{name},'%')
    </if>
</select>

在update语句中判断是否更新某一字段,只更新变化的字段,需要注意每个if元素SQL语句后面都有逗号,还有一个就是where语句前面的id=#{id}。

<update id="updateByIdSelective">
    UPDATE students SET
    <if test="name !=null and name != ''">
        name = #{name},
    </if>
    <if test="age !=null and age > 0">
        age = #{age},
    </if>
    <if test="hobby !=null and hobby != ''">
        hobby = #{hobby},
    </if>
    <if test="classAndGradeId !=null and classAndGradeId != ''">
        classAndGradeId = #{classAndGradeId},
    </if>
    id=#{id} WHERE id=#{id}
</update>

在insert语句中判断是否插入某个字段值,如果参数不空,则使用传入的值,否则使用数据库默认值,原理同上。不加代码了。

choose用法

choose可以实现if...else...的功能,一个choose至少有一个when标签,0~1个otherwise标签。

<select id="selectByIdOrName" resultMap="StudentsResult">
    SELECT id,name,age,hobby,classAndGradeId FROM students
    WHERE 1=1
    <choose>
        <when test="name !=null and name != ''">
            and name = #{name}
        </when>
        <when test="id !=null and id != ''">
            and id = #{id}
        </when>
        <otherwise>
            and 1=2
        </otherwise>
    </choose>
</select>

 

where/set/trim用法

where

可以将上面的where语句换成where标签,免去了where 1=1,同时标签中也会自动去掉第一and或or。

<select id="selectByName2" resultMap="StudentsResult">
    SELECT id,name,age,hobby,classAndGradeId FROM students
    <where>
        <if test="name !=null and name != '' ">
            AND name LIKE concat('%',#{name},'%')
        </if>
    </where>
</select>

set

       将上面set语句换成set标签,可以去掉最后的逗号,但是id=#{id}最好保留,如果set标签中没有内容则依然会报错。

<update id="updateByIdSelective2">
    UPDATE students
    <set>
        <if test="name !=null and name != ''">
            name = #{name},
        </if>
        <if test="age !=null and age > 0">
            age = #{age},
        </if>
        <if test="hobby !=null and hobby != ''">
            hobby = #{hobby},
        </if>
        <if test="classAndGradeId !=null and classAndGradeId != ''">
            classAndGradeId = #{classAndGradeId},
        </if>
        id=#{id},
    </set>
    <where>
        id=#{id}
    </where>
</update>

trim

where和set标签都可以用trim标签来实现。where标签对应trim标签如下:

<trimprefix=”WHERE” prefixOverrides=”AND | OR ”>...</trim>

set对应trim标签如下:

<trimprefix=”SET” suffixOverrides=”,”>...</trim>

trim标签有如下属性,prefix会增加指定前缀,prefixOverrides去掉匹配的前缀,suffix增加指定后缀,suffixOverrides去掉匹配的后缀。

foreach用法

foreach包含以下属性:collection为要迭代循环的属性名。item迭代的每个变量名。index索引的属性名(数组时为索引值,map类型时为key)。open整个循环内容开头的字符串。close整个循环内容结尾的字符串。separator每次循环插入的分隔符。如:

<delete id="deleteByIdSet">
    DELETE FROM students
    <where>
        id in
        <foreach collection="list" open="(" close=")" separator=","
            item="id" index="i">
            #{id}
        </foreach>
    </where>
</delete>

批量插入例子:

<insert id="insertList">
    INSERT INTO students(id,name,age,hobby,classAndGradeId)
    VALUES
    <foreach collection="list" item="stu" separator=",">
        (#{stu.id},#{stu.name},#{stu.age},#{stu.hobby},#{stu.classAndGradeId})
    </foreach>
</insert>

需要注意的是collection属性为一个集合的时候可以使用默认的“list”,如果为多个或使用其他变量名需要使用@Param注解。

Mybatis高级查询

一对多配置

model

这里一个两个model:班级和学生,一个班级包含多名学生。

public class ClassAndGrade {
    private String id;
    private String description;
    private List<Student> studentList;
}

 

public class Student {
    private String id;
    private String name;
    private int age;
    private String hobby;
    private String classAndGradeId;
}

ClassAndGrade.xml

在栗子中,一对多映射,一个班级下还有一个学生list,在resultMap标签中使用collection标签,property使用模型中变量名称即studentList,resultMap选择映射学生表的结果,要加上命名空间全称。

在SELECT语句中,使用left joinon,注意使用别名,防止命名冲突,如id。修改别名的话,标签中column也要改成别名,如下面标红位置。

<!DOCTYPE mapper
        PUBLIC "-//com.seu.sun.mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--对应接口的包名+接口名(无需实现)-->
<mapper namespace="com.seu.sun.mybatisConfig.mapper.ClassAndGradeMapper">

    <resultMap type="com.seu.sun.model.ClassAndGrade" id="ClassAndGradeResult">
        <id column="C_id" jdbcType="VARCHAR" property="id"/>
        <result column="description" jdbcType="VARCHAR" property="description"/>
        <!--一对多映射-->
        <collection property="studentList" resultMap="com.seu.sun.mybatisConfig.mapper.StudentMapper.StudentsResult"/>
    </resultMap>

    <select id="queryClassAndGradeList" resultMap="ClassAndGradeResult">
        SELECT a.id C_id,a.description,b.id,b.name,b.hobby,b.age
        FROM classandgrade a left join students b
        ON a.id = b.classAndGradeId
    </select>
    
</mapper>

记得在Configuration配置文件中添加新的xml文件的mapper标签。

testCRUD.java

public static void test1ToN(){
    ClassAndGradeMapper classAndGradeMapper = sqlSession.getMapper(ClassAndGradeMapper.class);
    List<ClassAndGrade> list= classAndGradeMapper.queryClassAndGradeList();
    for (ClassAndGrade c:list){
        System.out.println(c.getId()+c.getDescription());
        for(Student s:c.getStudentList()){
            System.out.println(s.getId()+s.getName()+s.getAge()+s.getHobby());
        }
    }
}

 

Spring集成Mybatis

pom.xml依赖

除了Spring和mybatis本身需要的依赖,还需要在pom.xml中添加依赖:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.1</version>
</dependency>

如遇到NoClassFound之类找不到类的错误,直接查找该类的依赖加上。。。

applicationContext.xml配置

<!--引入配置文件-->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:DBconfig.properties" />
</bean>

<!--配置数据库连接池-->
<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
    <property name="driver" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<!--集成Mybatis配置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--配置mybatis配置xml路径,除了数据源之外,对mybatis的各种配置仍然这样配置-->
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
    <!--配置数据源,必选项-->
    <property name="dataSource" ref="dataSource"/>
    <!--扫描xml映射文件的路径-->
    <property name="mapperLocations">
        <array>
            <value>classpath:mybatis/**/mapper/*.xml</value>
        </array>
    </property>
    <property name="typeAliasesPackage" value="com.seu.model"/>
</bean>

<!--配置MapperScannerConfigurer,自动扫描所有Mapper接口,使用时可以直接注入接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.seu.**.mapper"/>
</bean>

配置完后,写mapper接口和mapper.xml映射文件,相当于DAO层,mapper接口直接使用@Repository注射为Bean

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值