SpringBoot中Hibernate,Mybatis使用一点心得

使用SpringBoot开发有段时间了,主要是是从慕课上面看的两个课程入门的2小时学会Spring Boot、Spring Boot进阶之Web进阶,然后还购买了廖师兄的一个付费课程SpringBoot微信点餐系统,然后就开始SpringBoot开发了。因为之前写的是PHP,对Java完全不了解,感觉写起来非常繁琐,尤其是数据库这一块,操作非常麻烦,对查询返回的结果都要建一个对象。因为跟着课程来的,所以刚开始用的是hibernate,但是后来用了mybatis就放弃了hibernate,因为hibernate虽然不用写SQL但是不灵活。其实文章标题取得不是很准确,Hibernate是JPA规范的实现,主要是JPA和MyBatis进行对比的。看完本篇,你即可使用mybatis进行简单的开发。

Hibernate使用

MySQL user表

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL COMMENT '用户姓名',
  `user_phone` varchar(255) DEFAULT NULL COMMENT '用户电话',
  `user_password` varchar(255) DEFAULT NULL COMMENT '用户密码',
  `user_type` tinyint(4) DEFAULT NULL COMMENT '用户注册类型',
  `an_ticket` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '安券',
  `integral` float NOT NULL DEFAULT '0' COMMENT '积分',
  `user_photo` varchar(255) DEFAULT NULL COMMENT '用户头像',
  `user_input_invitation` varchar(255) DEFAULT NULL COMMENT '用户输入的邀请码',
  `user_invitation` varchar(255) DEFAULT NULL COMMENT '用户自己生成的邀请码',
  `login_time` timestamp NULL DEFAULT NULL COMMENT '上次登录时间',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `user_phone` (`user_phone`) USING BTREE,
  UNIQUE KEY `user_name` (`user_name`) USING BTREE,
  KEY `user_type` (`user_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8;

上面是user表,需要建一个对应的Java对象

import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.math.BigDecimal;
import java.util.Date;

/**
 * Create by fengguofei
 * Date: 2017/9/2
 * Time: 18:02
 */
@Entity
@Data
@DynamicUpdate
public class User {
    @Id
    @GeneratedValue
    private Integer userId;
    //用户姓名
    private String userName;
    //用户手机
    private String userPhone;
    //用户密码
    private String userPassword;
    //用户类型
    private Integer userType;
    //账户安券
    private BigDecimal anTicket;
    //账户积分
    private BigDecimal integral;
    //用户头像
    private String userPhoto;
    //用户填写的邀请码
    private String userInputInvitation;
    //用户自己生成的邀请码
    private String userInvitation;
    //用户上次登录时间
    private Date loginTime;
    //创建时间
    private Date createTime;
    //更新时间
    private Date updateTime;
}

上面是对应的Java对象,其中@Data是lombok插件,会自动帮你生成get,set,toString等常用的方法,非常方便。@Entity代表是数据库对象,供springboot扫描使用,@DynamicUpdate表示动态更新,主要是数据库中的updateTime会更新当对user表更新时。
MySQL列名字使用下划线分割,对应的Java对象使用驼峰规则,当然你也可以不这样做,使用@Column注解对列进行说明,@Table注解对表进行说明。

创建Repository对象

import com.anbixuan.dataobject.User;
import com.anbixuan.dto.interfaceMysqlData.LoginJudgeInterface;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * Create by fengguofei
 * Date: 2017/9/2
 * Time: 18:28
 */
public interface UserRepository extends JpaRepository{

    User findUserByUserPhone(String userPhone);

    User findUserByUserName(String userName);

    User findUserByUserInvitation(String invitation);

    User findUserByUserId(Integer userId);

    //根据用户的姓名,手机号码,邮箱来检测用户是否存在
    @Query(value = "select u.user_id,u.user_type, u.user_password\n" +
            "from `user` u,csoperson cp\n" +
            "where u.user_id = cp.user_id and (u.user_name=:userNameOrPhoneOrEmail or u.user_phone=:userNameOrPhoneOrEmail\n" +
            "or cp.csoperson_email = :userNameOrPhoneOrEmail)\n" +
            "UNION\n" +
            "select u.user_id,u.user_type, u.user_password\n" +
            "from `user` u,csocompany cc\n" +
            "where u.user_id = cc.user_id and (u.user_name=:userNameOrPhoneOrEmail or u.user_phone=:userNameOrPhoneOrEmail\n" +
            "or cc.csocompany_email = :userNameOrPhoneOrEmail)\n" +
            "UNION\n" +
            "select u.user_id,u.user_type, u.user_password\n" +
            "from `user` u,factor f\n" +
            "where u.user_id = f.user_id and (u.user_name=:userNameOrPhoneOrEmail or u.user_phone=:userNameOrPhoneOrEmail\n" +
            "or f.factor_email = :userNameOrPhoneOrEmail)\n" +
            "UNION\n" +
            "select u.user_id,u.user_type, u.user_password\n" +
            "from `user` u,producer p\n" +
            "where u.user_id = p.user_id and (u.user_name=:userNameOrPhoneOrEmail or u.user_phone=:userNameOrPhoneOrEmail\n" +
            "or p.producer_email = :userNameOrPhoneOrEmail)\n" +
            "UNION\n" +
            "select u.user_id,u.user_type, u.user_password\n" +
            "from `user` u,hospital h\n" +
            "where u.user_id = h.user_id and (u.user_name=:userNameOrPhoneOrEmail or u.user_phone=:userNameOrPhoneOrEmail\n" +
            "or h.hospital_email = :userNameOrPhoneOrEmail)",nativeQuery = true)
    List findUserByNameOrPhoneOrEmail(@Param("userNameOrPhoneOrEmail") String userNameOrPhoneOrEmail);
}

可以看到对数据库的查询十分方便,从函数的名字就能知道这个查询的意义。第一个查询是通过用户的手机号码、第二个查询是通过用户的名字,以此类推,其中可以使用@Query进行SQL编写,除此之外JPA还提供了像like、orderBy、Not、In等操作具体可以查看Spring Data JPA - Reference Documentation。

缺点

这个缺点是我自己的观点,可能不是很准确,因为我也不是很精通这个。一般建表都是创建主键,如果数据量很多,再加上索引。像其他的什么触发器、函数、外键都不创建,这些都由编程实现。问题出现了,JPA的动态查询如果关联表的话,你的Java对应的实体必须要创建外键,也就是manytomany、manytoone这些东西。此外你的查询结果如果只是一个表中的部分字段,你还要创建一个接口,比如上面的findUserByNameOrPhoneOrEmail查询就创建了一个LoginJudgeInterface接口,如果我查询结果很多,那岂不是要创建一堆接口。对我来多有点头疼。我的想法就是MySQL就是一个主键加索引,我的实体对象就是单个表的对应,甚至不需要创建表的实体对应,没有那些外键,查询要支持动态查询,返回结果也要比较方便。这些mybatis都能做的很好。

Mybatis

需要在pom.xml中引入mybatis依赖


    org.mybatis.spring.boot
    mybatis-spring-boot-starter
    1.2.0

在.yml配置文件中加一些配置

mybatis:
  mapper-locations: classpath:mapper/*.xml
  configuration:
    call-setters-on-nulls: true

配置的作用是表明.xml文件的位置,以及如果查询结果是null也要返回对应的字段

还需要在对应的Application上面加上@MapperScan的注解
SpringBoot中Hibernate,Mybatis使用一点心得_第1张图片
MapperScan.png
接下来就可以使用mybatis了。一般需要创建一个对应的Mapper接口,里面写上SQL操作,对应的具体操作既可以使用@Select注解,也可以使用.xml文件来写。举个例

通过@Select注解

import org.apache.ibatis.annotations.ResultType;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

/**
 * Create by fengguofei
 * Date: 2018/5/11
 * Time: 14:43
 */
public interface RoleMapper {


    @Select("select DISTINCT(ar.role_id) as `value`, ar.`name` as label from admin_role ar")
    @ResultType(List.class)
    List> getRoleList();

    @Select("select DISTINCT(ar.role_id) as roleId, ar.`name`, ar.introd from admin_role ar")
    @ResultType(List.class)
    List> getRoleIntrodList();

}

如果这个Mapper文件没有放到之前指定的目录下面,springboot是无法扫描到的,可以添加@Mapper注解进行扫描。
通过xml

import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**角色权限设置
 * Create by fengguofei
 * Date: 2018/5/21
 * Time: 19:54
 */
public interface RoleAuthSetMapper {

    /**
     * 获得角色列表
     * @return
     */
    List getRoleList();

    /**
     * 根据name获得菜单列表
     * @param roleName
     * @return
     */
    List getRoleListByName(@Param("roleName") String roleName);

    /**
     * 获得菜单权限列表
     * @return
     */
    List getMenuAuth();

    /**
     * 添加角色,批量插入数据库
     * @param roles
     */
    void addRole(List> roles);

    /**
     * 获得最大的role_id
     * @return
     */
    Integer getRoleIdMax();

    /**
     * 获得某个角色对应的权限菜单
     * @param roleId
     * @return
     */
    List getRoleMenuAuth(@Param("roleId") String roleId);

    /**
     * 删除指定role_id的角色
     * @param roleIds
     */
    void deleteRoles(List roleIds);
}

对应的xml文件





    

    

    
    
    
        insert into admin_role (role_id, `name`, introd, authority_id, change_by)
        VALUES
        
            (#{role.roleId}, #{role.roleName}, #{role.introd}, #{role.authorityId}, #{role.changeBy})
        
    
    
    

    
    
    
        delete from admin_role
        where role_id IN
        
            #{roleId}
        
    


.xml文件一定要放到之前设置的目录下面,其中namespace一定要指定具体的mapper文件,不然会报错。接下来说一下对应的增删改查、动态查询、like查询以及其他操作。

增删改查

插入一条数据

     /**
     * 插入一条敏感词数据
     * @param sensitiveMap
     */
    void insertSensitiveWord(Map sensitiveMap);
   
        INSERT admin_sensitive_word_dict(sensitive_word, remark, change_by)
        VALUE (#{word}, #{remark}, #{changeBy})
    

批量插入数据

    /**
     * 添加角色,批量插入数据库
     * @param roles
     */
    void addRole(List> roles);
    
        insert into admin_role (role_id, `name`, introd, authority_id, change_by)
        VALUES
        
            (#{role.roleId}, #{role.roleName}, #{role.introd}, #{role.authorityId}, #{role.changeBy})
        
    

就是通过foreach进行循环,foreach的具体用法可以查看官网

删除一条数据

    /**
     * 删除指定role_id的角色
     * @param roleId
     */
    void deleteRole(Integer roleId);
    
        delete from admin_role
        where role_id  = #{roleId}
    

批量删除数据

    /**
     * 删除指定role_id的角色
     * @param roleIds
     */
    void deleteRoles(List roleIds);
    
        delete from admin_role
        where role_id IN
        
            #{roleId}
        
    

插入一条数据

     /**
     * 插入后台用户
     * @param adminMap
     */
    Integer insertAdminUser(Map adminMap);
    
        insert admin_user (`name`, `password`, role_id, phone,
        branch_id, picture, education, graduate_school, major, id_number,
        change_by)
        value  (#{name}, #{password}, #{role_id}, #{phone},
        #{branch_id}, #{picture}, #{education}, #{graduate_school}, #{major}, #{id_number},#{change_by})

        
            SELECT LAST_INSERT_ID() as id
        
    

批量插入数据

    /**
     * 添加角色,批量插入数据库
     * @param roles
     */
    void addRole(List> roles);
    
        insert into admin_role (role_id, `name`, introd, authority_id, change_by)
        VALUES
        
            (#{role.roleId}, #{role.roleName}, #{role.introd}, #{role.authorityId}, #{role.changeBy})
        
    

更新一条数据

    /**
     * 更新后台用户
     * @param adminMap
     */
    void updateAdminUser(Map adminMap);
    
        update admin_user
        set `name` = #{userName}, role_id = #{role_id}, phone = #{phone},
        branch_id = #{branch_id}, education = #{education}, graduate_school = #{graduate_school},
        major = #{major}, id_number = #{idNumber},change_by = #{change_by}
        where id = #{userId}
    

动态查询

动态返回字段

    /**
     * 动态返回查询字段
     * @param startDate
     * @param endDate
     * @param columns
     * @return
     */
    List> getOffLineDateByColumnAll(String startDate,String endDate, String[] columns);
    

动态查询条件

动态and

    /**
     *根据name获得后台用户列表
     * @param name
     * @return
     */
    Page getAdminUserByNameList(@Param("sname") String name);
    

动态where

    /**
     * 根据name获得菜单列表
     * @param roleName
     * @return
     */
    List getRoleListByName(@Param("roleName") String roleName);
    

like

mybatis中like有几种写法,在此列举一下,以供学习。

通过bind

    

通过concat

        
            and td.create_time like CONCAT('%','${date}','%')
        

直接写

         
                ar.name like '%${roleName}%'
          

分页

通过PageHelper进行分页
引入依赖

        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            1.2.2
        

配置

/**
 * Create by fengguofei
 * Date: 2018/3/1
 * Time: 18:31
 */

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class MybatisConfig {
    //配置mybatis的分页插件pageHelper
    @Bean
    public PageHelper pageHelper(){
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("offsetAsPageNum","true");
        properties.setProperty("rowBoundsWithCount","true");
        properties.setProperty("reasonable","true");
        properties.setProperty("dialect","mysql");    //配置mysql数据库的方言
//        properties.setProperty("params","count=countSql");
        pageHelper.setProperties(properties);
        return pageHelper;
    }
}

接下来就可以使用了
.mapper接口

    /**
     *根据name获得后台用户列表
     * @param name
     * @return
     */
    Page getAdminUserByNameList(@Param("sname") String name);

.xml文件

    

service层

import com.github.pagehelper.PageInfo;
/**
 * Create by fengguofei
 * Date: 2018/4/16
 * Time: 16:07
 */
public interface AdminUserService {
    /**
     * 根据name获得后台用户列表
     * @param name
     * @param page
     * @param size
     * @return
     */
    PageInfo getAdminUserByNameList(String name, Integer page, Integer size);

serviceImpl层

import com.xxx.dataobject.mapper.admin.AdminUserMapper;
import com.anbixuan.service.admin.AdminUserService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Create by fengguofei
 * Date: 2018/4/16
 * Time: 16:09
 */
@Service
public class AdminUserServiceImpl implements AdminUserService {

    @Autowired
    private AdminUserMapper adminUserMapper;

    /**
     * 根据name获得后台用户
     * @param name
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo getAdminUserByNameList(String name, Integer page, Integer size) {
        PageHelper.startPage(page, size);
        Page> result =  adminUserMapper.getAdminUserByNameList(name);
        return result.toPageInfo();
    }

controller

    /**
     * @param name
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/get/user/by/name")
    public ResultVO getUserByName(@RequestParam(value = "name", defaultValue = "-1") String name,
                                   @RequestParam(value = "page", defaultValue = "1") Integer page,
                                   @RequestParam(value = "size", defaultValue = "10") Integer size,
                                   HttpServletRequest request){
        PageInfo adminUser = adminUserService.getAdminUserByNameList(name, page, size);
        Map resultMap = new LinkedHashMap<>();
        resultMap.put("number", adminUser.getTotal());
        resultMap.put("currentPage", page);
        resultMap.put("data",adminUser.getList());
        return ResultVOUtil.success(resultMap);
    }

其中ResultVO是自定义的返回json格式,大家可以不使用,直接返回也可以。

特殊符号

原符号       <        <=      >       >=       &        '        "
替换符号    <    <=   >    >=   &   '  "
例如:sql如下:
create_date_time >= #{startTime}  and  create_date_time <= #{endTime}

你可能感兴趣的:(SpringBoot中Hibernate,Mybatis使用一点心得)