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

mybatis的注解开发入门

程序员文章站 2022-05-24 20:18:10
...

mybatis注解开发:

        这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了。本次我们先围绕一些基本的 CRUD 来学习,再学习复杂映射关系及延迟加载。

mybatis常用注解说明:
mybatis的注解开发入门

前期准备工作:

使用IDEA软件制作:
新建Maven工程:
mybatis的注解开发入门
GroupID :是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
ArtifactID:是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
mybatis的注解开发入门
点击下一步,然后点击完成,maven工程就建好了
并且在pom.xml导入对应的坐标
mybatis的注解开发入门
在resources下创建配置文件等信息:

编写SqlMapperConfig.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">
   <!--上面是约束-->     
<!--mybatis的主配置文件-->
<configuration>
    <!--导入外部文件-->
    <properties resource="jdbcConfig.properties"></properties>

    <!--给实体类取别名-->
    <typeAliases>
        <package name="com.itmei.domain"/>
    </typeAliases>

    <!--环境配置-->
    <environments default="mysql">
        <!--mysql环境-->
        <environment id="mysql">
            <!--事务选择-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源-->
            <dataSource type="POOLED">
                <!--数据库的基本信息-->
                <property name="driver" value="${jdbc.driver}"/><!--这里的value要和外置文件的key一致-->
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--注册接口的别名-->
    <mappers>
        <package name="com.itmei.dao"/>
    </mappers>
</configuration>

编写jdbcConfig.properties:数据库的配置信息

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456

mybatis的注解开发入门
mybatis的注解开发入门

使用 Mybatis 注解实现基本 CRUD:

完成增删改查等操作:
创建User实体类
mybatis的注解开发入门
注意:这里我们故意使实体类的名称和数据库列名称不一样

使用注解方式开发持久层接口
mybatis的注解开发入门
我们先写2个查询方法,查询所有和查询一个用户信息:
其中里面的注解
    @Select:查询的语句
    @Results:各个属性的含义,id为当前结果集声明唯一标识,value值为结果集映射关系,@Result代表一个字段的映射关系,column指定数据库字段的名称,property指定实体类属性的名称,jdbcType数据库字段类型,@Result里的id值为true表明主键,默认false;使用@ResultMap来引用映射结果集,其中value可省略。

@Results相当于xml里面的< resultMap >标签
@ResultMap来引用映射结果集(一般使用在查询封装)
mybatis的注解开发入门
单个参数
    可以接收基本类型,对象类型,集合类型,都可以接收,mybatis可以直接使用这个参数,不用经过任何处理,同时#{}这里面的名称可以随便写。

注解所有的开发:

package com.itmei.dao;

import com.itmei.domain.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface UserDao {
    /**
     * 查询所有
     * @return
     */
    @Select("select * from user;")
    @Results(id = "userMap",
            value = {
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "birthday",property = "userBirthday"),
    })
    List<User> findAll();

    /**
     * 通过id查询一个用户
     * @param id
     * @return
     */
    @Select("select * from user where id=#{uid}") /*这里单个参数可以随便填写*/
    @ResultMap("userMap")
    User findById(Integer id);

    /**
     * 保存用户
     * @param user
     * @return
     */
    @Insert("insert into user  (username,sex,birthday,address) values (#{userName},#{userSex},#{userBirthday},#{userAddress})")
    @SelectKey(keyColumn = "id",keyProperty = "userId",before = false,resultType = Integer.class,
            statement = {"select last_insert_id()"})/*返回用户id的信息*/
    int saveUser(User user);

    /**
     * 用户的更新
     * @param user
     * @return
     */
    @Update("update user  set username=#{userName},sex=#{userSex},birthday=#{userBirthday},address=#{userAddress} where id=#{userId}")
    User updateUser(User user);

    /**
     * 删除用户
     * @param id
     * @return
     */
    @Delete("delete from user where id=#{userId}")
    int deleteUser(Integer id);

    /**
     * 查询总的信息(聚合函数)
     * @return
     */
    @Select("select count(*) from user ")
    int findTotal();

    /**
     * 模糊查询
     * @param name
     * @return
     */
    @Select("select * from user where username like #{userName}")
    @ResultMap("userMap")
    List<User> findByName(String name);


    /*这样我们就不要编写UserDao.xml映射文件*/
}

现在我们编写测试类:
UserTest测试类:

public class UserTest {
    private InputStream in;
    private  SqlSession session;
    private UserDao userDao;

    @Before/*在测试执行之前运行*/
    public void init() throws Exception{
        //1.读取配置文件
         in= Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2.创建工厂对象
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(in);
        //3.创建SqlSession对象 并且更改为自动添加事务
         session = factory.openSession(true);
        //4.通过session对象创建dao的代理对象
         userDao = session.getMapper(UserDao.class);
    }
    @After/*在测试执行之后运行*/
    public void end() throws Exception{
        //6.释放资源
        session.close();
        in.close();
    }
 }

mybatis的注解开发入门
所有的测试方法和代码:

package com.itmei.Test;

import com.itmei.dao.UserDao;
import com.itmei.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 UserTest {
    private InputStream in;
    private  SqlSession session;
    private UserDao userDao;

    @Before/*在测试执行之前运行*/
    public void init() throws Exception{
        //1.读取配置文件
         in= Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2.创建工厂对象
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(in);
        //3.创建SqlSession对象 并且更改为自动添加事务
         session = factory.openSession(true);
        //4.通过session对象创建dao的代理对象
         userDao = session.getMapper(UserDao.class);
    }
    @After/*在测试执行之后运行*/
    public void end() throws Exception{
        //6.释放资源
        session.close();
        in.close();
    }

    /**
     * 查询所有用户
     */
    @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);
        //结果:User{userId=41, userName='update user clear cache', userAddress='北京朝阳区', userSex='男', userBirthday=Tue Feb 27 17:47:08 CST 2018}
    }

    /**
     * 保存用户
     */
    @Test
    public void testSaveUser(){
        User user=new User();
        user.setUserName("MJW");
        user.setUserSex("男");
        user.setUserAddress("北京");
        user.setUserBirthday(new Date());
        System.out.println("用户信息"+user);
        //结果:用户信息User{userId=null, userName='MJW', userAddress='北京', userSex='男', userBirthday=Sun Jun 07 15:41:48 CST 2020}
         userDao.saveUser(user);
        System.out.println("用户信息"+user);
        //结果:用户信息User{userId=69, userName='MJW', userAddress='北京', userSex='男', userBirthday=Sun Jun 07 15:41:48 CST 2020}

    }

    /**
     * 更新用户,通过id
     */
    @Test
    public void testupdateUser(){
        User user=new User();
        user.setUserId(69);
        user.setUserName("update");
        user.setUserSex("男");
        user.setUserAddress("北京");
        user.setUserBirthday(new Date());
        userDao.updateUser(user);
        //调用方法查询用户
        User u = userDao.findById(69);
        System.out.println(u);
        //结果:User{userId=69, userName='update', userAddress='北京', userSex='男', userBirthday=Sun Jun 07 15:48:14 CST 2020}
    }


    /**
     * 删除一个用户
     */
    @Test
    public void testdelete(){
         userDao.deleteUser(68);
    }


    /**
     * 查询总记录数
     */
    @Test
    public void testFindTotal(){
        int total = userDao.findTotal();
        System.out.println("总记录数:"+total);
        //总记录数:17
    }


    /**
     * 模糊查询
     */
    @Test
    public void testFindByName(){
        String name="%王%";
        List<User> users = userDao.findByName(name);
        for (User user:users){
            System.out.println(user);
        }
        /*User{userId=42, userName='小二王', userAddress='北京金燕龙', userSex='女', userBirthday=Fri Mar 02 15:09:37 CST 2018}
        User{userId=43, userName='小二王', userAddress='北京金燕龙', userSex='女', userBirthday=Sun Mar 04 11:34:34 CST 2018}
        User{userId=46, userName='老王', userAddress='北京', userSex='男', userBirthday=Wed Mar 07 17:37:26 CST 2018}*/
    }


}

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

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

复杂关系映射的注解说明

mybatis的注解开发入门

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

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

添加 User 实体类及 Account 实体类
User 实体类

package com.itheima.domain;

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

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 */
public class User implements Serializable{

    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
    
    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 String getUserAddress() {
        return userAddress;
    }

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

    public String getUserSex() {
        return userSex;
    }

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

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

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

Account 实体类

package com.itheima.domain;

import java.io.Serializable;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 */
public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

    //多对一(mybatis中称之为一对一)的映射:一个账户只能属于一个用户
    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 getUid() {
        return uid;
    }

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

    public Double getMoney() {
        return money;
    }

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

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
}

mybatis的注解开发入门
添加Account账户的持久层接口并使用注解配置
mybatis的注解开发入门
添加UserDao用户的持久层接口并使用注解配置
mybatis的注解开发入门

测试一对一关联及延迟加载
mybatis的注解开发入门
mybatis的注解开发入门
           按正常道理当调用了findAll方法就会执行注解的所有数据,但是通过fetchType=FetchType.LAZY 实现延迟加载,在进行表的关联查询时,按照设置延迟规则推迟对关联对象的select查询。例如在进行一对多查询的时候,只查询出一方,当程序中需要多方的数据时,mybatis再发出sql语句进行查询,这样子延迟加载就可以的减少数据库压力。
mybatis的注解开发入门

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

需求:
         查询用户信息时,也要查询他的账户列表。使用注解方式实现。
分析:
         一个用户具有多个账户信息,所以形成了用户(User)与账户(Account)之间的一对多关系。

3.3.3.1 User 实体类加入 List< Account>
mybatis的注解开发入门
3.3.3.2 编写用户的持久层接口并使用注解配置
mybatis的注解开发入门
3.3.3.3 编写账户的持久层接口并使用注解配置
mybatis的注解开发入门
3.3.3.4 添加测试方法

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.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.List;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 */
public class UserTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;


    @Before//用于测试方法执行之前执行
    public void init() throws Exception {
        //1.读取配置,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory工厂
        factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        session = factory.openSession(true);
        //4.获取dao的代理对象
        userDao = session.getMapper(IUserDao.class);
    }
    @After//用于在测试方法执行之后执行
    public void destroy() throws Exception {
        //提交事务
        session.commit();
        //6.释放资源
        session.close();
        in.close();
    }

    @Test
    public  void  testFindAll(){
        List<User> users = userDao.findAll();
//        for(User account : users){
//            System.out.println("----每个账户的信息-----");
//            System.out.println(account);
//            System.out.println(account.getAccounts());
//        }
    }



}

       运行结果:因为使用延迟加载,如果使for循环可以使用那么会调用方法查询用户的信息,简称按需加载。
mybatis的注解开发入门

mybatis 基于注解的二级缓存

在 SqlMapConfig 中开启二级缓存支持
mybatis的注解开发入门
** 在持久层接口中使用注解配置二级缓存**
mybatis的注解开发入门

相关标签: java开发知识