Springboot 第三讲 对数据库的操作

这里讲解三种方式

JDBC操作
整合mybatis操作
使用JPA操作
注意:Demo只写Service层代码,操作数据库为test,表为Person
注意:新建的boot项目记得选spring web的起步依赖~

方式一 使用JDBC

1.导入springboot整合JDBC的起步依赖
    
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jdbcartifactId>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

2.编辑application.yml

配置数据源

#配置springboot整合数据库基于jdbc
spring:
  datasource:
    url: jdbc:mysql:///test?serverTimezone=GMT%2B8
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver

3.编写Service层代码
package com.demo.service.impl;

import com.demo.bean.Person;
import com.demo.service.PersonService;
import io.swagger.annotations.ApiImplicitParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PersonServiceImpl implements PersonService {
    //再springboot引入 spring-boot-starter 起步依赖后,就可以采用springboot提供的JDBCTemlate来进行数据库操作
    @Autowired
    private JdbcTemplate jdbcTemplate;

    //增加
    @Override
    public void add(Person person) {
        jdbcTemplate.update("insert into person(name,age) value (?,?)",person.getName(),person.getAge());

    }

    //修改
    @Override
    public void update(Long id,Person person) {
        jdbcTemplate.update("update person set name=?,age=? where id=?",person.getName(),person.getAge(),id);

    }

    //根据id查找
    @Override
    public Person findOne(Long id) {
        return jdbcTemplate.queryForObject("select * from person where id=?",new BeanPropertyRowMapper<>(Person.class),id);
    }

    //查找全部
    @Override
    public List<Person> findAll() {
        return jdbcTemplate.query("select * from person",new BeanPropertyRowMapper<>(Person.class));
    }

    //根据id删除
    @Override
    public void Delete(Long id) {
        jdbcTemplate.update("delete from person where id = ?",id);

    }
}

4.在启动类加个注解

@SpringBootApplication //加载配置文件用的

方式二:使用mybatis

mybatis的操作分为两种,使用映射文件,使用注解
1.映射文件的方式
1.引入springboot整合mybatis的起步依赖包

      
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
      
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.0.0version>
        dependency>

2.使用逆向工程生成映射文件以及mapper接口还有bean
目录结构
Springboot 第三讲 对数据库的操作_第1张图片
注意:映射文件指向的位置要一致
Springboot 第三讲 对数据库的操作_第2张图片

3.配置application.yml文件

#配置springboot整合数据库基于jdbc
spring:
  datasource:
    url: jdbc:mysql:///test?serverTimezone=GMT%2B8
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  #指明pojo所在位置
  type-aliases-package: com.demo.bean
  #指明mybatis映射文件所在目录
  mapper-locations: classpath:com/demo/mapper/*.xml

4.在启动类加个注解,指明mapper接口的位置
@MapperScan(basePackages = “com.demo.mapper”)
Springboot 第三讲 对数据库的操作_第3张图片
5.这里就都配置好啦,service和controller这里就不写了
2.注解的方式
1.引入springboot整合mybatis的起步依赖包,同上操作
2.配置application.yml文件
这里只配置数据源

#配置springboot整合数据库基于jdbc
spring:
  datasource:
    url: jdbc:mysql:///test?serverTimezone=GMT%2B8
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver

3.写mapper类来操作数据库
这里使用了注解
@Mapper
@Insert
@Delete()
@Update()
@Select()

package com.demo.mapper;
import com.demo.bean.Person;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface PersonMapper {
	//这里演示一个插入操作
    @Insert("insert into person(name,age) values (#{name},#{age})")
    public void add(Person p);
}

方式三 使用官方的JPA技术

1.导入相关依赖
     <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>
               
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.14version>
        dependency>
2.配置application.yml文件
#配置springboot整合数据库基于jdbc
spring:
  datasource:
    url: jdbc:mysql:///youlexuandb?serverTimezone=GMT%2B8
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource   #启用阿里的druid连接池
  jpa:
    hibernate:
      ddl-auto: update
    #在控制台输出执行的语句
    show-sql: true


jpa.hibernate.ddl-auto是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下:
·create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
·create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
·update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
·validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
到这就配置好了,然后书写对数据库的操作代码

3.创建一个bean

这里区别于其它多了几个注解
@Entity @Table @Id @GeneratedValue @Column

package com.demo.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
//Lombok生成getset方法以及有参无参构造函数
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity  //表示当前java类,对应映射到数据库一张表
@Table(name = "tb_user") //可以重命名生成表的表明,也可以不写该注解,默认是类名为表名
public class User implements Serializable {
    @Id   //表示当前属性id就是一个主键
    @GeneratedValue  //数据库自增
    private Long id;
    @Column(name="name",length =100,nullable = false)
    private String name;
    @Column(name="age",length =4,nullable = false)
    private int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
}

其它常用注解说明
@Entity 声明类为实体或表
@Table 声明表名
@Basic 指定非约束明确的各个字段
@Embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性
@Id 指定的类的属性,用于识别(一个表中的主键)
@GeneratedValue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值
@Transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中
@Column 指定持久属性栏属性
@SequenceGenerator 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列
@TableGenerator 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表
@AccessType 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量
@JoinColumn 指定一个实体组织或实体的集合。这是用在多对一和一对多关联
@UniqueConstraint 指定的字段和用于主要或辅助表的唯一约束
@ColumnResult 参考使用select子句的SQL查询中的列名
@ManyToMany 定义了连接表之间的多对多一对多的关系
@ManyToOne 定义了连接表之间的多对一的关系
@OneToMany 定义了连接表之间存在一个一对多的关系
@OneToOne 定义了连接表之间有一个一对一的关系
@NamedQueries 指定命名查询的列表
@NamedQuery 指定使用静态名称的查询

4.创建一个dao操作类并实现接口

相当于mybatis的mapper接口

package com.demo.dao;

import com.demo.bean.User;
import org.springframework.data.jpa.repository.JpaRepository;

//注意 泛型第一个是指定的类,第二个是主键的类型
//这个接口写好了所有增删查改的方法
public interface UserDao extends JpaRepository<User,Long> {
    
}

5.写一个service实现类
package com.demo.service.impl;

import com.demo.bean.User;
import com.demo.dao.UserDao;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
	//增加
    @Override
    public void add(User user){
        userDao.save(user);
    }
    //修改
    @Override
    public void update(User user){
        userDao.saveAndFlush(user);
    }
	//根据id查找
    public User findOne(Long id){
        return userDao.findById(id).get();
    }
	//根据id删除
    public void delete(Long id){
        userDao.deleteById(id);
    }
}

6.controller层略

当你启动启动类后会发现,数据库会自动新增两张表
Springboot 第三讲 对数据库的操作_第4张图片
第一张表是用来存储自增的id值的
第二张表就是通过注解来自动生成的表

-----------------------------------------------------

JPA的操作非常的简单,看看dao层,只是实现了接口,增删查改等基本操作就都实现了,但是有没有发现一个问题?复杂的查询或者其它条件查询并没有实现,那对于这个问题怎么处理呢?下面来安排

按照一定命名规范来自定义方法

举例:新增一个通过姓名来查询的方法
只需要在userDao类添加一行代码
public List findByName(String name);

package com.demo.dao;

import com.demo.bean.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

//注意 泛型第一个是指定的类,第二个是主键的类型
//这个接口写好了所有增删查改的方法
public interface UserDao extends JpaRepository {

    //自动推导,可以根据用户编写方法推导出用户查询意图,自动化实现队应查询
    public List findByName(String name);


}

可以发现,根本不需要自己写sql语句,是直接推导出了用户的意图直接实现了该方法,所以方法名必须按照约定去命名,这里就体现了约定大于配置的理念

其它方法命名规则如下图

Springboot 第三讲 对数据库的操作_第5张图片
Springboot 第三讲 对数据库的操作_第6张图片
Springboot 第三讲 对数据库的操作_第7张图片
那么问题又来了:我就要自己写sql语句可以吗?当然是可以的

JPA使用@Query实现自定义查询语句

这里有涉及到一个概念:JPQL语句,不能再像以前那种sql语法去写
在userDao类添加自定义方法
注意:
1.不能写表明,写的是bean类名
2.java8版本以上 传参前面要用@Param标示一下
3.JPQL语句接收参数用 : 参数名 的形式

//根据姓名的模糊查询
    @Query("select u from  User u where u.name like %:name%")
    public List queryName(@Param("name") String name);
如果想使用原始sql语句,那注解要这样写

注意:
1.要设置nativeQuery = true
2.接收参数还是用 : name 的形式

//根据姓名的模糊查询
    @Query(nativeQuery = true,value = "select * from tb_user where name = :name")
    public List queryname(String name);

补充知识:使用JPA快速的搭建一个Rest风格的接口

1.创建一个boot项目,启动依赖选三个
Springboot 第三讲 对数据库的操作_第8张图片
2.在pom.xml添加依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-restartifactId>
dependency>
 
   <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
   
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.14version>
        dependency>

3.修改application.properties为application.yml并添加以下代码

#配置springboot整合数据库基于jdbc
spring:
  datasource:
    url: jdbc:mysql:///test?serverTimezone=GMT%2B8
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource   #启用阿里的druid连接池
  jpa:
    hibernate:
      ddl-auto: update
    #在控制台输出执行的语句
    show-sql: true

注意:driver-class-name: com.mysql.cj.jdbc.Driver这里可能会报错
解决方法:加个依赖

 <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

4.写bean类

package com.demo.springbootjparestdemo.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
    @Id
    @GeneratedValue
    private int id;
    @Column(length = 100,nullable = false)
    private String name;
    @Column(length = 50)
    private double price;
}

5.实现JPA的操作接口类

package com.demo.springbootjparestdemo.dao;

import com.demo.springbootjparestdemo.bean.Car;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CarDao extends JpaRepository<Car,Long> {
}

到这就写完了!完全不用写什么接口实现类
测试:
直接访问地址
http://localhost:8080/cars/
会出现
Springboot 第三讲 对数据库的操作_第9张图片
就说明成功了
其它测试地址
Springboot 第三讲 对数据库的操作_第10张图片
删除
delete http://localhost:8080/cars/6

默认的访问路径是cars,当然也可以自定义访问路径
在操作接口类添加注解
@RepositoryRestResource(path=“www”)
Springboot 第三讲 对数据库的操作_第11张图片
修改后的访问路径是http://localhost:8080/www/

也可以自定义方法

在操作接口类添加方法

 @RestResource(path="findbynames")
    List<Car> findByName(@Param("name") String name);

访问接口
http://localhost:8080/www/search/findbynames?name=本田
注意:访问接口前多加了一个search

如果想不暴露这些方法

在操作接口类添加注解,多个参数用,隔开
关闭时
@RepositoryRestResource(exported=false)
开启时
@RepositoryRestResource(exported=true)

配置跨域

直接在实现了Respository接口的类上增加跨域注解@CrossOrigin即可
例:
@CrossOrigin(“http://localhost/9001”)

你可能感兴趣的:(Springboot 第三讲 对数据库的操作)