mybatis

1. MyBatis框架的作用

MyBatis框架是一个持久层框架,用于解决数据库持久化存储方案。

在Java语言中,可以通过JDBC技术实现数据库编程,但是,JDBC技术最大的问题就是编程套路固定,需要编写的代码大致相同,所以就产生了多种解决此问题的框架,例如Hibernate、MyBatis等,这些框架都可以大大的减少开发的工作量,甚至在某些细节的处理上,比手动编写JDBC代码处理得更好!

MyBatis就是可以明显简化开发的数据库持久化存储方案,开发者在使用MyBatis开发某个增/删/改/查功能时,只需要定义这个功能的抽象方法,及匹配的SQL语句即可!

除此以外,MyBatis还提供了数据缓存的处理等其它功能!

2. 创建项目

使用创建SpringMVC项目的步骤创建新的项目,Group Id使用cn.tedu,Artifact Id使用MyBatis,Packaing选择war(其实单机的MyBatis项目并不需要使用war,而只使用jar即可)。

关于MyBatis项目,必须添加的依赖有:

<!-- MyBatis框架 -->
<!-- 备选版本:3.5.0 ~ 3.5.3 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

<!-- MyBatis整合Spring框架 -->
<!-- 备选版本:2.0.0 ~ 2.0.3 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.3</version>
</dependency>

<!-- Spring-WEBMVC -->
<!-- 版本:不低于4.2即可 -->
<!-- 只使用MyBatis的话,其实,只需要spring-context即可,spring-webmvc中包含了spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>XXX</version>
</dependency>

<!-- Spring-JDBC -->
<!-- 版本:必须与使用的spring-webmvc保持一致 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>XXX</version>
</dependency>

<!-- MySQL Connector -->
<!-- 备选版本:8.0.12 ~ 8.0.18 -->
<!-- 备选版本:5.1.34 ~ 5.1.39 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.18</version>
</dependency>

<!-- 数据库连接池 -->
<!-- 备选版本:1.2, 1.2.2, 1.3, 1.4 -->
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>

<!-- 单元测试 -->
<!-- 备选版本:4.10, 4.11, 4.12 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

3. 连接数据库

首先,应该在src/main/resources下创建数据库连接相关配置的db.properties文件:

url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Chongqing
driver=com.mysql.cj.jdbc.Driver
username=root
password=root
initialSize=2
maxActive=10
将现有的Spring配置文件改名为spring-mvc.xml,并将此文件复制得到spring-dao.xml文件,在当前项目,后续就只使用spring-dao.xml文件即可!

在spring-dao.xml中,添加配置,读取以上db.properties,并将读到的值注入至BasicDataSource对象中:

<util:properties id="config"
    location="classpath:db.properties" />

<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="url" value="#{config.url}" />
    <property name="driverClassName" value="#{config.driver}" />
    <property name="username" value="#{config.username}" />
    <property name="password" value="#{config.password}" />
    <property name="initialSize" value="#{config.initialSize}" />
    <property name="maxActive" value="#{config.maxActive}" />
</bean>

完成后,在src/main/test下创建cn.tedu.mybatis.Tests单元测试类,在类中测试获取数据库连接对象:

public class Tests {

    ClassPathXmlApplicationContext ac;

    @Before
    public void doBefore() {
        ac = new ClassPathXmlApplicationContext(
            "spring-dao.xml");
    }

    @Test
    public void getConnection() throws SQLException {
        BasicDataSource dataSource
            = ac.getBean("dataSource", BasicDataSource.class);
        System.out.println(dataSource.getConnection());
    }

    @After
    public void doAfter() {
        ac.close();
    }
}

4. 接口与抽象方法

暂定当前目标:向数据库中插入1条用户数据。

MyBatis要求所有的抽象方法都应该定义在接口中,所以,先创建

cn.tedu.mybatis.UserMapper接口:

public interface UserMapper {
}

然后,需要在接口中定义“增加用户数据”的抽象方法,关于抽象方法的设计原则:

如果需要执行的数据操作是增、删、改类型的操作,应该将返回值类型声明为Integer,表示受影响的行数,如果不关心受影响的行数,也可以将返回值类型声明为void,但是,并不推荐这样做;如果需要执行的数据操作是查询操作,返回值类型可以设计为所期望的类型,只要能把查询结果都封装起来就可以;

方法名称可以自由定义,但是,不允许使用重载;

参数列表可以根据需要执行的SQL语句有哪些变量来决定,也可以参考以前学习JDBC时,SQL语句中需要写哪些问号来决定。

此次插入用户数据需要执行的SQL语句大致是:

insert into t_user (username,password,age,phone,email) values (?,?,?,?,?)
为了更加方便表达参数,可以将用户数据封装起来,所以,先创建cn.tedu.mybatis.User类,在类中声明与数据表字段对应的属性:

public class User {

    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String phone;
    private String email;

    // SET/GET/toString

}
则在接口中添加抽象方法:

Integer insert(User user);

完成以上代码后,目前,框架并不知道在哪个包中有哪些接口需要处理,所以,需要在spring-dao.xml添加配置MapperScannerConfigurer的basePackage属性:

<!-- MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 接口文件在哪里 -->
    <property name="basePackage" 
        value="cn.tedu.mybatis" />
</bean>

至此,关于接口与抽象方法部分的开发已经完成,但是,并不能执行任何测试检测开发与配置的效果!

5. 配置SQL语句

先下载http://doc.tedu.cn/config/mybatis-mapper.zip文件,解压得到SomeMapper.xml文件。

在项目的src/main/resources下创建名为mappers的文件夹,并将以上得到的XML文件复制到该文件夹中。

与此前的抽象方法对应的SQL语句都需要配置在这个XML文件中!

在XML中,首先需要添加根节点,并且,在该节点中配置namespace的属性,该属性值是需要对应的接口的全名:

<!-- namespace:对应哪个接口 -->
<mapper namespace="cn.tedu.mybatis.UserMapper">

</mapper>

然后,根据需要执行的SQL语句的种类,选择子级节点,以本次插入用户数据为例,则应该选择节点,这些节点必须指定id属性,其值是抽象方法的名称:

<!-- id:抽象方法的名称 -->
<insert id="insert">

</insert>

在该节点内部,配置需要执行的SQL语句:

<!-- id:抽象方法的名称 -->
<insert id="insert">
    INSERT INTO t_user (
        username, password, 
        age, phone, 
        email
    ) VALUES (
        #{username}, #{password}, 
        #{age}, #{phone}, 
        #{email}
    )
</insert>

以上代码中,使用#{}框住的名称,其实是User类中的属性名!

完成后,还需要配置SqlSessionFactoryBean,配置框架执行时使用的数据源,及配置SQL语句的XML文件的位置:

<!-- SqlSessionFactoryBean -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- XML文件在哪里 -->
    <property name="mapperLocations"
        value="classpath:mappers/*.xml" />
    <!-- 使用哪个数据源 -->
    <property name="dataSource" 
        ref="dataSource" />
</bean>

至此,开发任务完成,在Tests测试类中编写并执行单元测试:

@Test
public void insert() {
    // 获取UserMapper接口的代理对象
    UserMapper userMapper
        = ac.getBean("userMapper", UserMapper.class);
    // 测试功能
    User user = new User();
    user.setUsername("mapper");
    user.setPassword("8888");
    user.setAge(25);
    user.setPhone("13800139999");
    user.setEmail("mapper@163.com");
    Integer rows = userMapper.insert(user);
    System.out.println("rows=" + rows);
}

如果执行出错,并且,不是注册重复的用户名,则错误的原因可能在于:

配置的接口文件的位置有误,导致无法获取到名为userMapper的对象;

配置的XML文件的位置有误;

在XML文件中,根节点的namespace属性值有误;

在节点中,id属性的值并不是抽象方法的名称;

6. 开发新功能

6.1. 根据id删除指定的数据

在UserMapper接口中声明抽象方法:

Integer deleteById(Integer id);
在SomeMapper.xml中配置以上抽象方法的映射:

<delete id="deleteById">
    DELETE FROM t_user WHERE id=#{id}
</delete>
完成后,在Tests中编写并执行单元测试:

@Test
public void deleteById() {
    Integer id = 1;
    Integer rows = userMapper.deleteById(id);
    System.out.println("rows=" + rows);
}
6.2. 将所有用户的密码全部改为888888
在UserMapper接口中声明抽象方法:

Integer updatePassword(String newPassword);
在SomeMapper.xml中配置以上抽象方法的映射:

<update id="updatePassword">
    UPDATE t_user SET password=#{newPassword}
</update>
完成后,在Tests中编写并执行单元测试:

@Test
public void updatePassword() {
    String newPassword = "88888888";
    Integer rows = userMapper.updatePassword(newPassword);
    System.out.println("rows=" + rows);
}
6.3. 统计当前表中的用户数据的数量
在UserMapper接口中声明抽象方法:

Integer count();
在SomeMapper.xml中配置以上抽象方法的映射:

<select id="count" resultType="java.lang.Integer">
    SELECT COUNT(*) FROM t_user
</select>
注意:使用<select>节点时,必须配置resultType或resultMap属性中的某1个!

完成后,在Tests中编写并执行单元测试:

@Test
public void count() {
    Integer count = userMapper.count();
    System.out.println("count=" + count);
}
6.4. 查询指定id的数据
在UserMapper接口中声明抽象方法:

User findById(Integer id);
在SomeMapper.xml中配置以上抽象方法的映射:

<select id="findById" resultType="cn.tedu.mybatis.User">
    SELECT * FROM t_user WHERE id=#{id}
</select>
完成后,在Tests中编写并执行单元测试:

@Test
public void findById() {
    Integer id = 1;
    User user = userMapper.findById(id);
    System.out.println(user);
}
在测试时,如果存在与id匹配的数据,则返回匹配的数据,如果没有匹配的数据,则返回结果是null。

6.5. 查询当前表中所有用户的所有数据

在UserMapper接口中声明抽象方法:

List<User> findAll();
在SomeMapper.xml中配置以上抽象方法的映射:

<select id="findAll" resultType="cn.tedu.mybatis.User">
    SELECT * FROM t_user ORDER BY id
</select>
注意:如果查询结果是List类型的,在配置时,resultType也只需要声明List中的元素的类型!

完成后,在Tests中编写并执行单元测试:

@Test
public void findAll() {
    List<User> users = userMapper.findAll();
    System.out.println("count=" + users.size());
    for (User user : users) {
        System.out.println(user);
    }
}
如果表中并没有匹配的数据,查询结果是List类型时,也不会返回null,而是返回一个没有元素的List对象!

6.6. 将id=?的用户的电子邮箱改为?
在UserMapper接口中声明抽象方法:

Integer updateEmailById(
        @Param("id") Integer id, 
        @Param("email") String email);
注意:当抽象方法的参数的数量超过1个时,必须为每一个参数添加@Param注解,并在注解中指定名称,后续,在配置SQL语句时,在#{}中写的也将是注解中配置的名称!

在SomeMapper.xml中配置以上抽象方法的映射:

<update id="updateEmailById">
    UPDATE t_user SET email=#{email} WHERE id=#{id}
</update>
完成后,在Tests中编写并执行单元测试:

@Test
public void updateEmailById() {
    Integer id = 1;
    String email = "hello@163.com";
    Integer rows = userMapper.updateEmailById(id, email);
    System.out.println("rows=" + rows);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值