springboot基础-----连接并使用数据库

springboot基础-----连接并使用数据库

本文将介绍如何在springboot中连接mysql数据库,并介绍操作数据库的方式,spring jpa。本文是建立在已经学会如何构建springboot项目的基础上的。

  • 连接MySQL
  • spring jap简介
  • 编写实体类
  • 编写Dao层
  • 测试
  • 参考质料

连接MySQL

  • 连接的方法非常简单,只需做一点点的配件即可。
  • 先在pom.xml里面引入mysql-connector-java,引入的方式就是加上一段代码:
<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
</dependency>

上面这段代码要加在《dependencys>这组标签里面,学过html的应该大致理解它的意思。

  • 在application.properties文件里面添加配置。先讲解一下application.properties文件的作用,这是springboot唯一需要的属性配置文件,在里面可以添加你想要的属性,包括变量,常量以及一些项目属性。为了连接Mysql我们需要进行下面的一些配置:
spring.datasource.url=jdbc:mysql://localhost:3306/forum?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.username=root(根据你的MySQL用户名来填,一般都是root)
spring.datasource.password=你的密码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true //表示在控制台打印出执行的相关sql语句
  • 前面的spring.datasource都是关于连接数据库的,spring.jpa则是配置使用jpa的规则。
  • spring.jpa.hibernate.ddl-auto=update 表示每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新。
  • spring.jpa.hibernate.ddl-auto=create----每次运行该程序,没有表格会新建表格,表内有数据会清空
  • 一般我们使用的都是update的方式。

spring jap简介

JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring与EJB3.0的开发团队。

本来我是想用hibernate的,但是它的hibernateTamplate 已经被废除了。而jpa的使用又和hibernate非常类似,所以直接学习并使用了jpa。

编写实体类

先讲一下为什么要编写实体类。
我们编写的实体类其实就是为了和数据库的表形成一一映射的关系,这样实体里的每一个变量都与表格的每个字段相对应。我们在java中直接操作实体类里的对象,其实也等价于在操作数据库里的相应字段。

下面以一个例子来介绍如何编写实体类。
假定现在数据库里面有一张user表,表里有userid,userName,password等这些字段。
那么我现在要为这张表编写一个实体类,应该如何实现?
直接看下面的代码和注释。

package com.example.demo.domain;



import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName User
 * @Description TODO
 * @Auther ydc
 * @Date 2019/1/7 19:44
 * @Version 1.0
 **/
@Entity   //这是实体类的注解,必须要注明,表明这是一个实体类,关于springboot的注解,这里不再做深入介绍,先学会如何用,以后会介绍具体原理。
@Table(name = "user") //指定对应的数据库表
public class User extends BaseDomain implements Serializable {
//BaseDomain是我写的一个基类,现在可以先不管。
//implements Serializable 是为了实现序列化,原则上每一个实体类都需要序列化 
//下面定义的一些常量可以先不管
    public static final int user_locked = 1; //用户被锁定
    public static  final int user_unlocked = 0; // 用户未被锁定
    public  static  final int user_normal=0;//普通用户
    public static  final int user_Admin = 1; //版块管理员
    public static  final  int user_super_admin=2; //超级管理员


    @Id //使用Id注解,表明这是主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //主键生成策略是自增型
    @Column(name = "user_id")  //对应数据库的主键名
    private int userId;
  
    //除了主键需要特殊声明以外,其他的只需要声明对应的列就行,注意name=""必须是数据库里面的字段名称,否则会报错
    @Column(name = "user_name")
    private String userName;

    @Column(name="password")
    private String password;

    @Column(name = "credit")
    private int credits;

    @Column(name = "grade")
    private  String grade;

    @Column(name = "academy")
    private  String academy;

    @Column(name = "user_type")
    private  int user_type;

    @Column(name = "locked")
    private  int locked;

    @Column(name = "photo")
    private String photo;

    @Column(name = "last_ip")
    private String lastIp;

    @Column(name = "last_visit")
    private Date lastVisit;

    @Column(name = "signature")
    private String signature;

    @Column(name = "backPicture")
    private String backPicture;

    @Column(name = "email")
    private String email;

   //manyToMany是hibernate的一种写法,它表明当前的user这个表和另一个表是多对多的关系,利如学生和教室就是一个多对多的关系。具体参数含义可以直接百度一下,也可以先不管,因为这不重要,你只需要先知道可以这么用就行,需要的时候,直接查就行。
    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
    @JoinTable(name = "board_manager",joinColumns = {@JoinColumn(name = "user_id")},inverseJoinColumns = {@JoinColumn(name = "board_id")})
    private Set<Board> manBoards =new HashSet<Board>();

    public Set<Board> getManBoards() {
        return manBoards;
    }

//下面的get/set方法直接右键generate就可以生成,为了方便,还是都生成一下吧
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getBackPicture() {
        return backPicture;
    }

    public void setBackPicture(String backPicture) {
        this.backPicture = backPicture;
    }


    public String getPhoto() {
        return photo;
    }

    public int getUserId() {
        return userId;
    }

    public String getUserName() {
        return userName;
    }

    public String getPassword() {
        return password;
    }

    public int getCredits() {
        return credits;
    }

    public String getGrade() {
        return grade;
    }

    public String getAcademy() {
        return academy;
    }

    public int getUser_type() {
        return user_type;
    }

    public int getLocked() {
        return locked;
    }

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

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

    public void setPassword(String password) {
        this.password = password;
    }

    public void setCredits(int credits) {
        this.credits = credits;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public void setAcademy(String academy) {
        this.academy = academy;
    }

    public void setUser_type(int user_type) {
        this.user_type = user_type;
    }

    public void setLocked(int locked) {
        this.locked = locked;
    }

    public void setPhoto(String photo) {
        this.photo = photo;
    }

    public String getLastIp() {
        return lastIp;
    }

    public void setLastIp(String lastIp) {
        this.lastIp = lastIp;
    }

    public Date getLastVisit() {
        return lastVisit;
    }

    public void setLastVisit(Date lastVisit) {
        this.lastVisit = lastVisit;
    }
//实体类为了测试方便需要提供有参数的构造函数和无参数构造函数,直接右键generate就行
    public User(String userName, String password, int credits, String grade, String academy, int user_type, int locked, String photo, String lastIp, Date lastVisit) {

        this.userName = userName;
        this.password = password;
        this.credits = credits;
        this.grade = grade;
        this.academy = academy;
        this.user_type = user_type;
        this.locked = locked;
        this.photo = photo;
        this.lastIp = lastIp;
        this.lastVisit = lastVisit;
    }

    public User() {
    }
}

编写Dao层

先讲一下Dao层的作用,一般我们开发java web都是按MVC模式进行开发的,因为这样分层开发可以让开发更简单有效。而Dao层则是实现数据库与后端交互的桥梁。
下面通过代码来讲解Dao层。

package com.example.demo.dao;

import com.example.demo.domain.User;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * @ClassName UserDao
 * @Description TODO
 * @Auther ydc
 * @Date 2019/1/7 20:26
 * @Version 1.0
 **/
 //jpa已经为我们封装好了大量的sql语句,我们先继承一下JpaRepository<>里面的两个参数分别填写实体类和主键的类型(Long和integer都行)
public interface UserDao extends JpaRepository<User,Long> {
//findByUserName这个函数将会被解析成sql语句,select * from User where username=userName。 
    User  findByUserName(String userName);
    //同理findByUserId也会被解析成对应的sql语句
    User findByUserId(int userId);

    @Override
    //Page<>是jpa为我们封装好的分页类,用于实现页面的分页效果
    Page<User> findAll(Pageable pageable);

    Page<User> findByUserNameLike(String userName,Pageable pageable);
    //findByUserNameLike 是实现模糊查询的方式,在传入的参数userName中,需要我们设定好占位符 % .
    List<User> findByUserNameLike(String userName);

//jpa没有提供更新语句,所以更新语句需要我们自己编写,语法格式和sql非常类似,不过注意我们要直接对实体类对象进行操作,具体写法参照下面的来就行。
//一般来说,有更新语句还需要提供@Transactional事物注解,但是在实践的项目中,我们不直接使用Dao层函数,而是新建一个service层,所以注解我直接加在了Service类里面。(注意,如果想直接使用dao层的更新语句,则必须在@Modifying前面加上@Transactional)
    @Modifying
    @Query(value = "update User as u set u.password=:password where u.userId=:id")
    //=:password 其中  :  是占位符的意思,我们通过传入的参数,利用@Param("password") 就可以将我们想要更新的参数传给sql语句了。
    void updatePasswordById(@Param("password") String password, @Param("id") int id);


    @Modifying
    @Query(value = "update User as u set u.user_type=:utype where u.userId=:id")
    void updateUserTypeById(@Param("utype")int type,@Param("id") int id);


    @Modifying
    @Query(value = "update User as u set u.grade=:grade where u.userId=:id")
    void updateUserGradeById(@Param("grade") String grade,@Param("id") int id);


    @Modifying
    @Query(value = "update User as u set u.academy=:academy where u.userId=:id")
    void updateUserAcademyById(String academy,int id);


    @Modifying
    @Query(value = "update User as u set u.locked=:lock where u.userId=:id")
    void updateUserLockedById(@Param("lock") int sta,@Param("id") int id);

    @Modifying
    @Query(value = "update User as u set u.credits = :credits where u.userId=:id")
    void updateUserCreditById(@Param("credits") int credit,@Param("id") int id);

    @Modifying
    @Query(value = "update User as u set u.photo = :photo where u.userId=:id")
    void updateUserPhoto(@Param("photo") String  photo,@Param("id") int id);

    @Modifying
    @Query(value = "update User as u set u.signature=:signature where u.userId=:id")
    void updateUserSignature(@Param("signature") String  signature,@Param("id") int id);


    @Modifying
    @Query(value = "update User as u set u.userName=:name where u.userId=:id")
    void updateUserName(@Param("name") String  name,@Param("id") int id);

}

前面介绍了查找和更新,插入还没有写。其实插入很简单,jpa已经封装好了sava函数,需要传一个实体类对象进去,这样就完成保存了。
至于删除函数,jpa也提供了解析语句,将findBy… 的find 换成delete就行。这里不再详细讲解。

  • Pageable 是spring封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。下面介绍一下如何使用
	int page=1,size=10;
	Sort sort = new Sort(Direction.DESC, "UserId");
    Pageable pageable = new PageRequest(page, size, sort);
    //意思是将数据库里的数据分页,每页10条数据,我现在需要第1页的数据,这样就会给我们返回第1页的10条数据
    findALL(pageable);

测试

springboot为我们提供了专门的测试文件test。
打开test目录,你可以直接在…applicationTest里进行测试,也可以新建java类来测试,新建java类后,需要注解

@RunWith(SpringRunner.class)
@SpringBootTest

下面我直接给出测试Userdao的代码和注释。

package com.example.demo.daoTest;

import com.example.demo.dao.*;
import com.example.demo.domain.*;
import com.example.demo.service.LoginLogService;
import com.example.demo.service.imp.BoardServiceImp;
import com.example.demo.service.imp.LoginLogServiceImp;
import com.example.demo.service.imp.TopicServiceImp;
import com.example.demo.service.imp.UserServiceImp;
import org.assertj.core.error.ShouldBeAfterYear;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * @ClassName LoginDaoTest
 * @Description TODO
 * @Auther ydc
 * @Date 2019/1/8 10:18
 * @Version 1.0
 **/
@RunWith(SpringRunner.class)
@SpringBootTest
public class LoginDaoTest {

//利用spring注解,我们就可以直接使用userDao了,想要了解注解的知识,可以到我之前的博客里看。
   @Autowired
    private  UserDao userDao;
  

  

    @Test
    @Transactional //之所以加上@Transactional是因为,我直接使用了userDao,里面有update函数,需要事物注解。
    public void updateTopic(){
           userDao.findByUserName("ydc");//根据名字ydc去数据库里面查,之前我已经在数据库里面插入了数据。

    }
}

###参考质料

jpa参考博客
Spring Data JPA 参考指南
spring框架IOC容器的理解

你可能感兴趣的:(Java)