欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存

程序员文章站 2022-07-12 22:37:23
...


1.常用的注解说明

@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用

1.Mybatis常用的注解开发CRUD

Maven项目里面的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>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Mybatis_annotation</artifactId>
    <version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.20</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.12</version>
    </dependency>
</dependencies>
</project>

项目概况:
Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存
不需要写映射配置
jdbcConfig.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/li
jdbc.username=root
jdbc.password=517818li

1.1设置实体类User

故意设置于=与数据库列名不一致

package Annotation.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable{
    private Integer userId;
    private String userName;
    private Date userBirthDay;
    private String userSex;
    private String userAddress;

    @Override
    public String toString() {
        return "User[" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userBirthDay=" + userBirthDay +
                ", userSex='" + userSex + '\'' +
                ", userAddress='" + userAddress + '\'' +
                ']';
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getUserBirthDay() {
        return userBirthDay;
    }

    public void setUserBirthDay(Date userBirthDay) {
        this.userBirthDay = userBirthDay;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }
}

1.2配置用户接口IUserDao

需要注意的是: @Update("update user set username=#{userName},sex=#{userSex},address = #{userAddress},birthday = #{userBirthDay} where id = #{userId} ")
#{…}里面的要与实体类定义的列名对应

package Annotation.dao;

import Annotation.domain.User;
import org.apache.ibatis.annotations.*;

import java.util.List;
public interface IUserDao {
    /**1. 查询操作**/
    @Select("select * from user ")
    @Results(id = "userMap", value = {
            @Result(id = true, column = "id", property = "userId"),
            @Result(column = "username", property = "userName"),
            @Result(column = "sex", property = "userSex"),
            @Result(column = "address", property = "userAddress"),
            @Result(column = "birthday", property = "userBirthDay")
    })
    List<User> findAll();
    /**2.根据id查询用户*/
    @Select("select * from user where id = #{uid}")
    @ResultMap("userMap")
    User findById(Integer uid);
    /**3.保存操作
     *
     */
    @Insert("insert into user(username,sex,birthday,address)values(#{userName},#{userSex},#{userBirthDay},#{userAddress})")
    @SelectKey(keyColumn="id",keyProperty="userId",resultType=Integer.class, before = false, statement = { "select last_insert_id()" })
    int saveUser(User user);
    /**
     * 4.更新操作
     */
    @Update("update user set username=#{userName},sex=#{userSex},address = #{userAddress},birthday = #{userBirthDay} where id = #{userId} ")
    int updateUser(User user);
    /**
     * 5.删除操作
     */
    @Delete("delete from user where id = #{uid}")
    int deleteUser(Integer userId);
    /**
     * 6.使用聚合函数查询
     */
    @Select("select count(*) from user")
    int findTotal();
    /**
     * 7.模糊查询
     */
    @Select("select * from user where username like #{username} ")
    @ResultMap("userMap")
    List<User> findByName(String name);
}

1.3SqlMapConfig.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="jdbcConfig.properties"></properties>
    <!-- 配置别名的注册 -->
    <typeAliases>
        <package name="Annotation.domain.User"/>
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置 mysql 的环境 -->
        <environment id="mysql">
            <!-- 配置事务的类型是 JDBC -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射信息 -->
    <mappers>
        <!-- 配置 dao 接口的位置,它有两种方式
        第一种:使用 mapper 标签配置 class 属性
        第二种:使用 package 标签,直接指定 dao 接口所在的包
        -->
        <package name="Annotation.dao"/>
    </mappers>
</configuration>

1.4测试类

import Annotation.dao.IUserDao;
import Annotation.domain.User;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class AnnotationTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;

    private IUserDao userDao;

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
        for(User user : users) {
            System.out.println(user);
        } }
    /**
     * 测试查询一个
     */
    @Test
    public void testFindById() {
        User user = userDao.findById(41);
        System.out.println(user);
    }
/**
 * 测试保存
 */
    @Test
    public void testSave() {
    User user = new User();
    user.setUserName("mybatis annotation");
    user.setUserSex("男");
    user.setUserAddress("北京市顺义区");
    user.setUserBirthDay(new Date());
    int res = userDao.saveUser(user);
    System.out.println("影响数据库记录的行数:"+res);
    System.out.println("插入的主键值:"+user.getUserId());
}

    /**
     * 测试更新
     */
    @Test
    public void testUpdate() {
        User user = userDao.findById(43);
        user.setUserBirthDay(new Date());
        user.setUserSex("女");
        int res = userDao.updateUser(user);
        System.out.println(res);
    }

    /**
     * 测试删除
     */
    @Test
    public void testDelete() {
        int res = userDao.deleteUser(63);
        System.out.println(res);
    }

    /**
     * 测试查询使用聚合函数
     */
    @Test
    public void testFindTotal() {
        int res = userDao.findTotal();
        System.out.println(res);
    }

    /**
     * 测试模糊查询
     */
    @Test
    public void testFindByName() {
        List<User> users = userDao.findByName("%王%");
        for (User user : users) {
            System.out.println(user);
        }
    }



    @Before//junit 的注解
    public void init() throws Exception {
//1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
//3.创建 session
        session = factory.openSession();
//4.创建代理对象
        userDao = session.getMapper(IUserDao.class);
    }

    @After//junit 的注解
    public void destroy() throws Exception {
//提交事务
        session.commit();
//释放资源
        session.close();
//关闭流
        in.close();
    }
}

2.使用注解实现复杂关系映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置来实现
在使用注解开发时我们需要借助 @Results 注解, @Result 注解, @One 注解, @Many 注解。

2.1 复杂关系映射的注解说明

@Results 注解
代替的是标签<resultMap>
该注解中可以使用单个@Result 注解,也可以使用@Result 集合
@Results{@Result(),@Result()})或@Results@Result())
@Resutl 注解
代替了 <id>标签和<result>标签

@Result 中 属性介绍:
id 是否是主键字段
column 数据库的列名
property 需要装配的属性名
one 需要使用的@One 注解(@Result(one=@One)()))
many 需要使用的@Many 注解(@Result(many=@many)()))

@One 注解(一对一)
代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
使用格式:
@Result(column=" ",property="",one=@One(select=""))
@Many 注解(多对一)
代替了<Collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
(一般为 ArrayList)但是注解中可以不定义;
使用格式:
@Result(property="",column="",many=@Many(select=""))

2.2 使用注解实现一对一复杂关系映射及延迟加载

需求:
加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。(注解方式实现)

2.2.1Account账户实体类

package Annotation.domain;

public class Account {
    private Integer id;
    private Integer uid;
    private Double money;
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Account[" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                ']';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }
}

2.2.2IAccountDao的接口

package Annotation.dao;

import Annotation.domain.Account;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface IAccountDao{
    @Select("select * from account")
    @Results(id="accountMap",
            value= {
                    @Result(id=true,column="id",property="id"),
                    @Result(column="uid",property="uid"),
                    @Result(column="money",property="money"),
                    @Result(column="uid",
                            property="user",
                            one=@One(select="Annotation.dao.IUserDao.findById",
                                    fetchType= FetchType.LAZY) )
            })
    List<Account> findAll();
}

2.2.3添加测试方法

  private IAccountDao accountDao;
    @Test
    public void testFindAl(){
        accountDao = session.getMapper(IAccountDao.class);
        List<Account> accounts = accountDao.findAll();
        for (Account account : accounts) {
            System.out.println(account);
            System.out.println(account.getUser());
        }
    }

2.2.4测试结果

Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存

2.3使用注解实现一对多复杂关系映射

Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存

2.3.1将Account加入User中

package Annotation.domain;

public class Account {
    private Integer id;
    private Integer uid;
    private Double money;
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Account[" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                ']';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }
}

2.3.2在IAccountDao接口中加入


    @Select("select  * from account where uid = #{id}")
    @ResultMap("accountMap")
    List<Account> findByUid(Integer id);

2.3.3在IUserDao中修改Results

many = @Many(select =“Annotation.dao.IAccountDao.findByUid”)多对多

 @Results(id = "userMap", value = {
            @Result(id = true, column = "id", property = "userId"),
            @Result(column = "username", property = "userName"),
            @Result(column = "sex", property = "userSex"),
            @Result(column = "address", property = "userAddress"),
            @Result(column = "birthday", property = "userBirthDay"),
            @Result(column = "id",property = "accounts",
            many = @Many(select ="Annotation.dao.IAccountDao.findByUid"))
    })

2.3.4加入测试方法(一个用户能对应多个账户)

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
        for(User user : users) {
            System.out.println("用户信息");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }
    }

2.3.5查询结果

Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存

3 mybatis 基于注解的二级缓存

3…1 在 SqlMapConfig 中开启二级缓存支持

<!-- 配置二级缓存 --> <settings>
<!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/>
</settings>

3.2 在持久层接口中使用注解配置二级缓存

/**
* 
* <p>Title: IUserDao</p>
* <p>Description: 用户的持久层接口</p>
* <p>Company: http://www.itheima.com/ </p>
*/
@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
public interface IUserDao {}
相关标签: JAVA mybatis