图书管理借阅系统(SpringBoot项目)

前后端分离项目

一:效果展示

图书借阅系统效果展示

二:代码实现

一、设计数据库(表的设计)

1、首先我们要进入图书系统必须要登录,验证身份之后才可进入,角色有:普通用户、管理员

2、其次是图书表

3、图书属于哪个出版社我们也单独设计了一张表

4、然后是借阅表,用户借阅图书的记录

5、最后当用户没有归还图书时,管理员可以进行催还的操作

一共是五张表:

用户表:

sql 复制代码
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `type` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

图书表:

sql 复制代码
CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `author` varchar(255) DEFAULT NULL,
  `pid` int(255) DEFAULT NULL,
  `number` int(11) DEFAULT NULL,
  `status` int(11) DEFAULT NULL,
  `is_del` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

出版社表:

sql 复制代码
CREATE TABLE `press` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

借阅表:

sql 复制代码
CREATE TABLE `borrow` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bid` int(255) DEFAULT NULL,
  `uid` int(255) DEFAULT NULL,
  `j_time` datetime DEFAULT NULL,
  `g_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

消息表:

sql 复制代码
CREATE TABLE `mq` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `msg` varchar(255) DEFAULT NULL,
  `time` datetime DEFAULT NULL,
  `uid` int(11) DEFAULT NULL,
  `status` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

以上就是该项目中所需的表

二、登录权限

登录页,用户输入用户名和密码,后端校验用户名和密码是否匹配,若匹配则返回登录成功信息,并显示当前登录成功的用户身份 (普通用户 或 管理员),登录后跳转到图书列表页,否则返回登录失败信息

三、图书管理页面

根据角色的不同,显示不同的内容,管理员登陆,可以显示所有图书的信息,但不能显示借阅按钮,可以对图书进行,增删改查。普通用户登陆,可以查询图书信息,并只显示未借阅的图书。并显示借阅按钮。

四、借阅操作

普通用户,点击借阅按钮之后,确定图书的借阅时间,并将图书状态设置为"已借阅"状态,当借阅成功之后,对数据的借阅次数进行+1操作。

五、借阅列表

普通用户,只能看到,自己借阅的书单,并显示"归还"按钮,如果书没有归还,显示归还按钮。当用户点击"归还"按钮之后,将归还时间设置为点击归还的时间。将书的状态,设置为"未借阅"。当管理员进入到借阅列表页面,可以看到所有的借阅记录。催书功能。管理员可以指定某一个未归还的书本信息,并通过RabbitMQ,模拟发送短信,给用户。当用户登陆之后,可以接收发送过来的短信消息。

另外该项目中额外增加了导入导出功能

代码

登录前端:

html 复制代码
<template>
  <div class="home">
    <el-form v-model="login">
      用户名:<el-input type="text" v-model="login.username" style="width: 300px"></el-input><br>
      账号:<el-input type="text" style="width: 300px" v-model="login.password"></el-input><br>
      <el-button type="primary" @click="toLogin()">登录</el-button>
    </el-form>

  </div>
</template>

<script>
export default {
  data(){
    return{
      login:{}

    }
  },
  methods:{
    toLogin(){
      this.axios.post("/user/login",this.login).then(res=>{
        if(res.data.code==0){
          this.$message.error(res.data.msg);
        }else{
          localStorage.setItem("user",JSON.stringify(res.data.data));
          alert("欢迎回来:"+(res.data.data.type==1?"管理员":"普通用户"));
          this.$router.push("/book");
        }
      })
    }
  }


}
</script>

登录后端:

java 复制代码
package cn.jiyun.controlller;

import cn.jiyun.commons.Results;
import cn.jiyun.mapper.UserMapper;
import cn.jiyun.pojo.User;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.JsonObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin
@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @RequestMapping("login")
    public Results login(@RequestBody User user){
        LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
        qw.eq(User::getUsername,user.getUsername());
        qw.eq(User::getPassword,user.getPassword());
        User user1 = userMapper.selectOne(qw);
        if(user1==null){
            return Results.error("账号或密码错误,请重试!");
        }
        redisTemplate.boundValueOps("BookUser").set(JSONObject.toJSONString(user1));
        return Results.success(user1);
    }
}

图书列表展示前端:

html 复制代码
<template>
  <div>
    <h1>当前登录的用户是:{{this.login.type==1?'管理员':'普通用户'}}</h1>
    书名:
    <el-input v-model="requestParam.name" style="width: 200px" placeholder="请输入内容"></el-input>
    作者:
    <el-input v-model="requestParam.author" style="width: 200px" placeholder="请输入内容"></el-input>
    出版社:
    <el-select v-model="requestParam.pid" placeholder="请选择">
    <el-option
        v-for="item in pressList"
        :key="item.id"
        :label="item.name"
        :value="item.id">
    </el-option>
  </el-select>
    <el-button type="primary" size="mini" @click="findList">搜索</el-button>
    <el-button type="primary" size="mini" @click="borrowList">借阅列表</el-button>
    <el-button type="primary" v-if="login.type==1" size="mini" @click="daochu">导出</el-button>
    <el-upload
        class="avatar-uploader"
        action="http://localhost:82/book/daoru"
        :show-file-list="false"
      :on-success="handleAvatarSuccess">
<!--      :before-upload="beforeAvatarUpload">-->
      <el-button type="primary" size="mini">导入</el-button>
    </el-upload>

    <el-button type="primary" v-if="login.type!=1" size="mini" @click="xiaoxi">消息列表</el-button>
    <el-dialog title="消息" :visible.sync="dialogxiaoxiVisible">
      <el-table
          :data="mqList"
          stripe
          style="width: 100%">
        <el-table-column
            prop="msg"
            label="消息">
        </el-table-column>
        <el-table-column
            prop="time"
            label="时间">
        </el-table-column>
        <el-table-column
            prop="status"
            label="状态">
          <template slot-scope="scope">
            {{scope.row.status==1?'未读':'已读'}}
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scope">
            <el-button v-if="scope.row.status==1"
                       size="mini"
                       @click="yidu(scope.row.id)">已读
            </el-button>

          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
    <el-table
        :data="page.records"
        stripe
        style="width: 100%">
      <el-table-column
          prop="id"
          label="编号">
      </el-table-column>
      <el-table-column
          prop="name"
          label="姓名">
      </el-table-column>
      <el-table-column
          prop="author"
          label="作者">
      </el-table-column>
      <el-table-column
          prop="pname"
          label="出版社">
      </el-table-column>
      <el-table-column
          prop="number"
          label="借阅次数">
      </el-table-column>
      <el-table-column
          prop="status"
          label="当前借阅状态">
        <!--template:模板 自定义展示内容-->
        <template slot-scope="scope">
          {{ scope.row.status == 1 ? '借阅中' : '未借阅' }}
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button v-if="login.type==1"
              size="mini"
              @click="handleEdit(scope.row)">修改
          </el-button>
          <el-button v-if="login.type==1"
              type="danger"
              size="mini"
              @click="handleDel(scope.row.id)">删除
          </el-button>
          <el-button v-if="login.type!=1"
              type="danger"
              size="mini"
              @click="handleJieShu(scope.row.id)">借阅
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!--分页-->
    <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="page.current"
        :page-sizes="[4, 6, 8, 10]"
        :page-size="page.size"
        layout="total, sizes, prev, pager, next, jumper"
        :total="page.total">
    </el-pagination>
<!--    修改弹窗-->
    <el-dialog title="修改书籍" :visible.sync="dialogFormVisible">
      <el-form :model="form">
        <el-form-item label="活动名称" :label-width="formLabelWidth">
          <el-input v-model="form.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="作者" :label-width="formLabelWidth">
          <el-input v-model="form.author" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="借阅次数" :label-width="formLabelWidth">
          <el-input v-model="form.number" type="number" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="出版社" :label-width="formLabelWidth">
          <el-select v-model="form.pid" placeholder="请选择">
            <el-option
                v-for="item in pressList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="updateBook()">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import axios from "axios";

export default {
  data(){
    return{
      login:{},
      pressList:[],
      requestParam:{},
      pageParam:{
        current:1,
        size:2,
      },
      page:{},
      dialogFormVisible:false,
      form:{},
      formLabelWidth:"200px",
      mqList:[],
      dialogxiaoxiVisible:false,
      mqLen:0,

    }
  },
  methods:{
    yidu(id){
      this.axios.post("/book/yidu?id="+id).then(res=>{
        this.findMQList();
      })
    },
    borrowList(){
      this.$router.push("/borrowList");

    },
    handleJieShu(id){
      this.axios.post("/book/jieyue?id="+id).then(res=>{
        if(res.data.code!=0){
          this.$message.success(res.data.msg);
          this.findList();
        }
      })
    },
    handleDel(id){
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.axios.post("/book/delBookById?id="+id).then(res=>{
          if(res.data.code!=0){
            this.$message.success(res.data.msg);
            this.findList();
          }
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });

    },
    updateBook(){
      this.axios.post("/book/updateBook",this.form).then(res=>{
        if(res.data.code!=0){
          this.$message.success(res.data.msg);
          this.findList();
          this.dialogFormVisible=false;
        }
      })
    },
    handleAvatarSuccess(){
      this.findList();
    },
    handleEdit(t){
      this.form=t;
      this.dialogFormVisible=true;

    },
    handleSizeChange(val) {
      this.pageParam.size=val;
      this.findList();
    },
    handleCurrentChange(val) {
      this.pageParam.current=val;
      this.findList();
    },
    findList(){
      this.axios.post(`/book/bookList?current=${this.pageParam.current}&size=${this.pageParam.size}`,this.requestParam).then(res=>{

         this.page=res.data.data;


      })
    },
    findPressList(){
      this.axios.post(`/book/findPressList`).then(res=>{
        this.pressList=res.data;
      })
    },
    daochu(){
      location.href="http://localhost:82/book/daochu";
    },
    findMQList(){
      this.axios.post(`/book/findMQList`).then(res=>{
        this.mqList=res.data;
        // this.mqLen=this.mqList.length;
        // alert(this.mqList[0].msg)
        if(this.mqList.length>0){
          this.dialogxiaoxiVisible=true;
        }
      })
    },
    xiaoxi(){
      this.dialogxiaoxiVisible=true;
    }
  },
  created() {
    this.login=JSON.parse(localStorage.getItem("user"));
    this.findPressList();
    this.findList();
      this.findMQList();
  }
}
</script>

图书列表展示、借阅记录展示后端:

java 复制代码
package cn.jiyun.controlller;

import cn.jiyun.commons.Results;
import cn.jiyun.excel.BookExcel;
import cn.jiyun.mapper.BorrowMapper;
import cn.jiyun.mapper.MQMapper;
import cn.jiyun.mapper.PressMapper;
import cn.jiyun.mapper.UserMapper;
import cn.jiyun.pojo.*;
import cn.jiyun.service.BookService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jdk.nashorn.internal.parser.TokenStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@CrossOrigin
@RestController
@RequestMapping("book")
public class BookController {
    @Autowired
    BookService bookService;
    @Autowired
    PressMapper pressMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private BorrowMapper borrowMapper;
    @Autowired
    MQMapper mqMapper;
    @Autowired
    UserMapper userMapper;
    @RequestMapping("bookList")
    public Results bookList(int current, int size, @RequestBody Book book){
        User bookUser = JSONObject.parseObject(redisTemplate.boundValueOps("BookUser").get().toString(), User.class);

        if (bookUser.getType()==2) {
            book.setStatus(2);
        }
        Page<Book> bookPage = bookService.bookList(current, size, book);
        return Results.success(bookPage);
    }

    @RequestMapping("findPressList")
    public List<Press> findPressList(){
        return pressMapper.selectList(null);
    }
    @RequestMapping("updateBook")
    public Results updateBook(@RequestBody Book book){
        return bookService.updateBook(book);
    }
    @RequestMapping("delBookById")
    public Results delBookById(Integer id){
        return bookService.delBookById(id);
    }
    @RequestMapping("jieyue")
    public Results jieyue(Integer id){
        User bookUser = JSONObject.parseObject(redisTemplate.boundValueOps("BookUser").get().toString(), User.class);
        Book book=bookService.findBookById(id);
        Borrow borrow = new Borrow();
        borrow.setBid(book.getId());
        borrow.setUid(bookUser.getId());
//        borrow.setGTime();
        borrow.setJTime(LocalDateTime.now());
        borrowMapper.insert(borrow);
        book.setNumber(book.getNumber()+1);
        book.setStatus(1);
        bookService.updateBook(book);
        return Results.success("借阅"+book.getName()+"成功");
    }
    @RequestMapping("borrowList")
    public Results borrowList(int current,int size){
        User bookUser = JSONObject.parseObject(redisTemplate.boundValueOps("BookUser").get().toString(), User.class);
        Borrow borrow = new Borrow();

        if(bookUser.getType()!=1){
            borrow.setFlag(bookUser.getId());
        }
        Page<Borrow> borrowPage1 = new Page<>(current, size);
        borrowPage1 = borrowMapper.selectFindAll(borrowPage1,borrow);
        return Results.success(borrowPage1);
    }
    @RequestMapping("guiHuan")
    public Results guiHuan(Integer id){

        Borrow borrow = borrowMapper.selectById(id);
        Book book = bookService.findBookById(borrow.getBid());
        book.setStatus(2);
        bookService.updateBook(book);
        borrow.setGTime(LocalDateTime.now());
        borrowMapper.updateById(borrow);
        return Results.success("归还成功");
    }
    @RequestMapping("cuiHuan")
    public Results cuiHuan(Integer id){
        Borrow borrow = borrowMapper.selectById(id);
        Book book = bookService.findBookById(borrow.getBid());
        MQ mq = new MQ();
        User user = userMapper.selectById(borrow.getUid());
        User bookUser = JSONObject.parseObject(redisTemplate.boundValueOps("BookUser").get().toString(), User.class);
        mq.setMsg(user.getUsername()+"你好,您借阅的《"+book.getName()+"》图书请尽快归还");
        mq.setTime(LocalDateTime.now());
        mq.setUid(borrow.getUid());
        mq.setStatus(1);//1未读,2已读
        mqMapper.insert(mq);
        return Results.success("催还成功");
    }
    @RequestMapping("findMQList")
    public List<MQ> mqList(){
        User bookUser = JSONObject.parseObject(redisTemplate.boundValueOps("BookUser").get().toString(), User.class);
        MQ mq = new MQ();
        mq.setUid(bookUser.getId());
        return mqMapper.selectLis(mq);
    }
    @RequestMapping("yidu")
    public Results yidu(Integer id){
        MQ mq = mqMapper.selectById(id);
        mq.setStatus(2);
        mqMapper.updateById(mq);
        return Results.success("");
    }
    @RequestMapping("daochu")
    public void daochu(HttpServletResponse response) throws IOException {
        List<Book> records = bookService.bookList(1, 10000, new Book()).getRecords();
        List<BookExcel> bookExcels = new ArrayList<>();
        for (Book boo : records) {
            BookExcel bookExcel = new BookExcel();
            bookExcel.setId(boo.getId());
            bookExcel.setName(boo.getName());
            bookExcel.setPname(boo.getPname());
            bookExcel.setStatus(boo.getStatus()==1?"借阅中":"未借阅");
            bookExcel.setNumber(boo.getNumber());
            bookExcel.setAuthor(boo.getAuthor());
            bookExcels.add(bookExcel);
        }
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("玩家列表.xlsx", "UTF-8"));
        response.setHeader("Connection", "close");
        response.setHeader("Content-Type", "application/octet-stream");
        EasyExcel.write(response.getOutputStream())
                .excelType(ExcelTypeEnum.XLSX)
                .head(BookExcel.class)
                .sheet("图书列表")
                .doWrite(bookExcels);
    }
@RequestMapping("daoru")
public void daoru(MultipartFile file) throws IOException {
//        先得到文件的输入流
//        需要从ecxel中获取数据存入该实体类中\
    System.out.println(file.getSize());
    InputStream inputStream = file.getInputStream();
    EasyExcel.read(inputStream, BookExcel.class, new ReadListener<BookExcel>(){

        @Override
        public void invoke(BookExcel bookExcel, AnalysisContext analysisContext) {
            Book book = new Book();
            book.setName(bookExcel.getName());
            int status=bookExcel.getStatus().equals("借阅中")?1:2;
            LambdaQueryWrapper<Press> qw = new LambdaQueryWrapper<>();
            qw.eq(Press::getName, bookExcel.getPname());
            Press press = pressMapper.selectOne(qw);
            book.setStatus(status);
            book.setPid(press.getId());
            book.setAuthor(bookExcel.getAuthor());
            book.setNumber(bookExcel.getNumber());
            book.setIsDel(0);
            bookService.add(book);
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        }
    }).excelType(ExcelTypeEnum.XLSX).sheet(0).doRead();


}

}

借阅记录展示前端:

html 复制代码
<template>
  <div class="home">
    <el-table
        :data="page.records"
        stripe
        style="width: 100%">
      <el-table-column
          prop="bname"
          label="图书">
      </el-table-column>
      <el-table-column
          prop="username"
          label="借阅人">
      </el-table-column>
      <el-table-column
          prop="jTime"
          label="借阅时间">
      </el-table-column>
      <el-table-column
          prop="gTime"
          label="归还时间">
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button
                     type="danger" v-if="loginUser.type==2&&scope.row.gTime==null"
                     size="mini"
                     @click="guiHuan(scope.row.id)">归还
          </el-button>
          <el-button
              type="danger" v-if="loginUser.type==1&&scope.row.gTime==null"
              size="mini"
              @click="cuiHuan(scope.row.id)">催还
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!--分页-->
    <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="page.current"
        :page-sizes="[4, 6, 8, 10]"
        :page-size="page.size"
        layout="total, sizes, prev, pager, next, jumper"
        :total="page.total">
    </el-pagination>

  </div>
</template>

<script>
export default {
  data(){
    return{
      page:{},
      pageParam:{
        current:1,
        size:3,
      },
      loginUser:{}
    }
  },
  methods:{
    guiHuan(id){
      this.axios.post(`/book/guiHuan?id=`+id).then(res=>{
        this.$message.success(res.data.msg);
        this.borrowList();
      })
    },
    cuiHuan(id){
      this.axios.post(`/book/cuiHuan?id=`+id).then(res=>{
        this.$message.success(res.data.msg);
        this.borrowList();
      })
    },
    handleSizeChange(val) {
      this.pageParam.size=val;
      this.borrowList();
    },
    handleCurrentChange(val) {
      this.pageParam.current=val;
      this.borrowList();
    },
    borrowList(){
      this.axios.post(`/book/borrowList?current=${this.pageParam.current}&size=${this.pageParam.size}`).then(res=>{
        this.page=res.data.data;
      })
    }

  },
  created() {
    this.loginUser = JSON.parse(localStorage.getItem("user"));
    this.borrowList();
  }


}
</script>

以上就是项目的完整代码,希望对每一个在Java道路上努力的人有帮助

相关推荐
小陈工3 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花7 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸7 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain7 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希8 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神8 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员8 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java8 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿9 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴9 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存