SpringBoot集成Hibernate实例

1. hibernate和mybatis的区别

一、两者最大的区别

针对简单逻辑,Hibernate与MyBatis都有相应的代码生成工具,可以生成简单基本的DAO层方法。

针对高级查询,MyBatis需要手动编写SQL语句,以及ResultMap,而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于流程。

二、开发难度对比

Hibernate的开发难度大于MyBatis,主要由于Hibernate比较复杂,庞大,学习周期比较长。

MyBatis则相对简单,并且MyBatis主要依赖于生气了的书写,让开发者刚进更熟悉。

三、sql书写比较

Hibernate也可以自己写sql来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性,不过Hibernate具有自己的日志统计。

MyBatis的sql是手动编写的,所以可以按照要求指定查询的字段,不过没有自己的日志统计,所以要借助Log4j来记录日志。

四、数据库扩展性计较

Hibernate与数据库具体的关联在XML中,所以HQL对具体是用什么数据库并不是很关心

MyBatis由于所有sql都是依赖数据库书写的,所以扩展性、迁移性比较差。

五、缓存机制比较

Hibernate的二级缓存配置在SessionFactory生成配置文件中进行详细配置,然后再在具体的表对象映射中配置那种缓存。

MyBatis的二级缓存配置都是在每个具体的表对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓冲机制,并且MyBatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。
  
两者比较
因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL,所以在使用二级缓存时如果出现脏数据,系统会报出错误提示。 而MyBatis在这一方面使用二级缓存时需要特别小心,如果不能完全去顶数据更新操作的波及范围,避免cache的盲目使用,否则,脏数据的出现会给系统的正常运行带来很大的隐患。

2.新建Springboot项目添加依赖

在这里插入图片描述

pom文件中依赖如下:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.traffic</groupId>
    <artifactId>trafficwarning</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>trafficwarning</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>
        <!--极光推送-->
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jpush-client</artifactId>
            <version>3.2.9</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>

        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.2</version>
        </dependency>
        <!--MySQL依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>


        <resources>
            <!-- maven项目中src源代码下的xml等资源文件编译进classes文件夹,
              注意:如果没有这个,它会自动搜索resources下是否有mapper.xml文件,
              如果没有就会报org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.pet.mapper.PetMapper.selectByPrimaryKey-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>

            <!--将resources目录下的配置文件编译进classes文件  -->
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>

    </build>


</project>

重点来了application.properties的配置:
注:此时和mybatis 配置略有不同,除了常规数据源的配置外,还需要对hibernate的jap 进行设置,具体如下:



# 数据库访问配置
# 主数据源,默认的

#端口号
server.port=8085

#----------------------database-------------------------
spring.datasource.url = jdbc:mysql://localhost:3306/companytest?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username = name
spring.datasource.password = password
com.mysql.cj.jdbc.Driver= com.mysql.jdbc.Driver


#server.port=9090



# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
spring.datasource.useGlobalDataSourceStat=true


#JPA Configuration:
spring.jpa.database=MYSQL
# Show or not log for each sql query
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true  
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update  
#spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy  
#spring.jpa.database=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

spring.jpa.hibernate.ddl-auto 的配置需要留意,如果配置了create,则每次重启服务会将连接的对接数据表进行情况,一般情况我们有update.
create: 每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。

create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。

update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。

validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

3.实体类注解应用

package com.example.springboothibernate.entity;





import javax.persistence.*;

/**
 *  springboot集成hibernate 实例
 * @Entity用来标识这是一个实体类
 * @Id hibernate的特征,必须要一个id不然会报错
 * @Column(name = "sid") 用来跟表的字段做个映射,如果名字相同就不需要写
 * @return
 */
@Entity
@Table(name="student")
public class Student {
    @Id
    @Column(name = "sId")
    @GeneratedValue(strategy= GenerationType.AUTO)
    private  int sId;
    @Column(name = "sName")
    private  String sName;
    @Column(name = "classId")
    private  String classId;


    public int getsId() {
        return sId;
    }

    public void setsId(int sId) {
        this.sId = sId;
    }

    public String getsName() {
        return sName;
    }

    public void setsName(String sName) {
        this.sName = sName;
    }

    public String getClassId() {
        return classId;
    }

    public void setClassId(String classId) {
        this.classId = classId;
    }
}

dao层代码

package com.example.springboothibernate.dao;

import com.example.springboothibernate.entity.Student;

import java.util.List;
import java.util.Optional;


import org.springframework.data.repository.CrudRepository;

public interface StudentMapper extends CrudRepository<Student,String> {
    /**
     * 新增学生
     * @param student
     * @return
     */
    Student save(Student student);

    /**
     * 删除学生
     * @param
     */
    void deleteBysId(int sId);

    /**
     * 查询
     * @return
     */
    List<Student>  findAll();

    /**
     * 查询单个
     * @param
     * @return
     */
    Student findBysId(int sId);
}

Service and Impl

package com.example.springboothibernate.service;

import com.example.springboothibernate.entity.Student;
import org.springframework.stereotype.Service;

import java.util.List;


public interface StudentService {

        /**
         * 添加
         */
        void insertStudent(Student student);

        /**
         * 删除
         */
        void deleteStudent(int sId);

        /**
         * 修改
         */
        void updateStudent(Student student);

        /**
         * 查询
         */
        List<Student> getStudent();

        /**
         * 查询单个
         */
        Student getStudentBysId(int sId);



}


package com.example.springboothibernate.serviceImpl;

import com.example.springboothibernate.dao.StudentMapper;
import com.example.springboothibernate.entity.Student;
import com.example.springboothibernate.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

        @Autowired
        private StudentMapper studentMapper;

        @Override
        public void insertStudent(Student student) {
            studentMapper.save(student);
        }

        @Override
        @Transactional
        public void deleteStudent(int sId) {
            studentMapper.deleteBysId(sId);
        }

        @Override
        public void updateStudent(Student student) {
            studentMapper.save(student);
        }

        @Override
        public List<Student> getStudent() {
            return  studentMapper.findAll();
        }

        @Override
        public Student getStudentBysId(int sId) {
            return studentMapper.findBysId(sId);
        }
    }


注意:
在进行对表的Delete需要在Service层上进行@Transaction注解,否则无法顺利执行,爆出如下异常

 "timestamp": "2019-12-17T05:58:57.054+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call",
    "path": "/demo01/delete"

大概意思是:在需要事务的方法上,没有开启事务,结果就操作需要事务的方法比如保存,修改数据库数据方法。

修复方式也特别简单,在需要事务的方法上加入加上注解:@Transactional即可。

Controller

package com.example.springboothibernate.controller;


import com.example.springboothibernate.entity.Student;
import com.example.springboothibernate.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
    @RestController
    @RequestMapping("/demo01")
    public class HibernateController {
        @Autowired
        StudentService studentService;

        /**
         * 添加
         * @return
         */
        @RequestMapping("/insert")
        public String insert(HttpServletRequest request, HttpServletResponse response){
            int sId=Integer.parseInt(request.getParameter("sId"));
            String sName=request.getParameter("sName");
            String classId=request.getParameter("classId");
            Student student = new Student();
            student.setsId(sId);
            student.setsName(sName);
            student.setClassId(classId);
            studentService.insertStudent(student);
            return "SUCCESS";
        }

        /**
         * 删除
         * @param
         * @return
         */
        @RequestMapping("/delete")
        public String delete(HttpServletRequest request, HttpServletResponse response){
            int sId=Integer.parseInt(request.getParameter("sId"));
            studentService.deleteStudent(sId);
            return "SUCCESS";
        }

        /**
         * 修改
         * 修改跟添加调用的是同一个方法如果id相同就改变数据没有就创建数据
         * @param student
         * @return
         */
        @RequestMapping("/update")
        public String update(HttpServletRequest request, HttpServletResponse response){
            Student student = new Student();
            int sId=Integer.parseInt(request.getParameter("sId"));
            String sName=request.getParameter("sName");
            String classId=request.getParameter("classId");
            student.setsId(sId);
            student.setsName(sName);
            student.setClassId(classId);
            studentService.updateStudent(student);
            return "SUCCESS";
        }

        /**
         * 查询
         * @return
         */
        @RequestMapping("/getStudent")
        public List<Student> getStudent(){

            return studentService.getStudent();
        }

        /**
         * 根据sid查询
         * @param
         * @sId
         */
        @RequestMapping("/studentId")
        public Student getStudentBysId(HttpServletRequest request, HttpServletResponse response){

            int sId=Integer.parseInt(request.getParameter("sId"));
            return studentService.getStudentBysId(sId);
        }

    }



以上只是简单的CRUD,剩下一对多和多对多将在后期进行更新。

你点的每一个赞,我都认真当成了喜欢

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值