36、Java——一个案例学会三层架构对数据表的增删改查

news2024/12/24 8:13:57

✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:Java案例分享专栏
✨特色专栏:国学周更-心性养成之路
🥭本文内容:一个案例学会三层架构对数据表的增删改查

文章目录

    • 案例要求
    • 建book表
    • 配置连接数据库
    • 创建实体类:Book类
    • 工具类
      • DBUtils数据库工具类
      • DateUtils日期类
    • 数据访问层DAO层
      • BookDao接口
      • BookDaoImpl类(实现BookDao接口)
    • 服务层Service层
      • BookService接口
      • BookServiceImpl类(实现BookService接口)
    • 视图层View层
      • TestBookServiceImpl测试类
    • 完整代码

在这里插入图片描述

案例要求

  使用读取配置文件的形式连接数据库,利用三层架构对book表进行增删改查操作。增加了接口知识点的优化,便于方法名的统一命名。

book表字段如下
  bid int 非空 主键 自增长 唯一 -->图书编号
  isbn varchar(20) 非空 唯一 -->国际标准书号
  name varchar(20) 非空 -->书名
  author varchar(20) 非空 -->作者
  press varchar(20) 非空 -->出版社
  press double 非空 -->价格
  classification varchar(20) 非空 -->分类

建book表

CREATE TABLE `book` (
  `bid` int(11) NOT NULL AUTO_INCREMENT COMMENT '图书编号',
  `isbn` varchar(20) NOT NULL COMMENT '国际标准书号',
  `name` varchar(20) NOT NULL COMMENT '书名',
  `author` varchar(20) NOT NULL COMMENT '作者',
  `press` varchar(20) NOT NULL COMMENT '出版社',
  `price` double NOT NULL COMMENT '价格',
  `classification` varchar(20) NOT NULL COMMENT '分类',
  PRIMARY KEY (`bid`),
  UNIQUE KEY `isbn` (`isbn`)
) 
);

配置连接数据库

  添加mysql-connector-java-5.1.0-bin.jar文件并使用。
  添加db.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/java221803
username=root
password=huanghuang

创建实体类:Book类

  定义一个Book类,添加和Book表字段相同的私有变量

	// 定义属性
	private int bid;
	private String isbn;
	private String name;
	private String author;
	private String press;
	private double price;
	private String classification;

  添加一个无参构造

	public Book() {
		super();
	}

  添加一个全部字段的有参构造

	public Book(int bid, String isbn, String name, String author, String press,
			double price, String classification) {
		super();
		this.bid = bid;
		this.isbn = isbn;
		this.name = name;
		this.author = author;
		this.press = press;
		this.price = price;
		this.classification = classification;
	}

  添加一个不带aid字段的有参构造

	public Book(String isbn, String name, String author, String press,
			double price, String classification) {
		super();
		this.isbn = isbn;
		this.name = name;
		this.author = author;
		this.press = press;
		this.price = price;
		this.classification = classification;
	}

  给私有变量添加get/set方法

	public int getBid() {
		return bid;
	}

	public void setBid(int bid) {
		this.bid = bid;
	}

	public String getIsbn() {
		return isbn;
	}

	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getPress() {
		return press;
	}

	public void setPress(String press) {
		this.press = press;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getClassification() {
		return classification;
	}

	public void setClassification(String classification) {
		this.classification = classification;
	}

  重写ToString方法

	@Override
	public String toString() {
		return "Book [bid=" + bid + ", isbn=" + isbn + ", name=" + name
				+ ", author=" + author + ", press=" + press + ", price="
				+ price + ", classification=" + classification + "]";
	}

工具类

  将一些重复的功能封装成一些工具。

DBUtils数据库工具类

  声明一个ThreadLocal对象,用来存储Connection连接对象;注册驱动、获取连接、然后释放资源方法。

	private static final Properties PROPERTIES = new Properties();
	// 声明一个ThreadLocal<Connection>对象,用来存储Connection连接对象
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

	static {
		InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
		try {
			PROPERTIES.load(is);
			// 1、注册驱动
			Class.forName(PROPERTIES.getProperty("driver"));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
		// 2、获取连接方法
	public static Connection getConnection() {
		Connection connection = threadLocal.get();
		// 2、获取连接对象
		try {
			// 如果连接对象为null,创建一个连接对象
			if (connection == null) {
				connection = DriverManager.getConnection(
						PROPERTIES.getProperty("url"),
						PROPERTIES.getProperty("username"),
						PROPERTIES.getProperty("password"));
				threadLocal.set(connection);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return connection;

	}

	// 3、释放资源方法
	public static void closeAll(ResultSet resultSet, Statement statement,
			Connection connection) {
		try {
			if (resultSet != null) {
				resultSet.close();
			}
			if (statement != null) {
				statement.close();
			}
			if (connection != null) {
				connection.close();
				// 移除 ThreadLocal<Connection> 对象
				threadLocal.remove();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

  开启事务

	public static void startTransaction() {
		Connection connection = getConnection();
		try {
			connection.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

  提交事务

	public static void commitTransaction() {
		Connection connection = getConnection();
		try {
			connection.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(null, null, connection);
		}
	}

  回滚事务

	public static void rollbackTransaction() {
		Connection connection = getConnection();
		try {
			connection.rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(null, null, connection);
		}
	}

DateUtils日期类

public class DateUtils {
	// 声明一个SimpleDateFormat类型的静态常量
	public static final SimpleDateFormat SIMPLEDATEFORMAT=new SimpleDateFormat("yyyy-MM-dd");

	// 定义方法实现将字符串类型的数据转换成java.util.Date类型
	public static java.util.Date strToUtilDate(String strDate){
		try {
			return SIMPLEDATEFORMAT.parse(strDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 定义方法实现将java.util.Date类型转换为字符串
	public static String utilDateToString(java.util.Date utilDate){
		return SIMPLEDATEFORMAT.format(utilDate);
	}
	
	// 定义方法实现架构java.util.Date类型转换为java.sql.Date类型
	public static java.sql.Date utilDateToSqlDate(java.util.Date utilDate){
		return new java.sql.Date(utilDate.getTime());
	}
}

数据访问层DAO层

  DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封装了增删改查基本操作,建议DAO只做原子操作,增删改查。

BookDao接口

package cn.bdqn.dao;
import java.util.List;
import cn.bdqn.entity.Book;

public interface BookDao {

	//增
	int insert(Book book);
	
	//删
	int delete(int bid);
	
	//改
	int update(Book book);
	
	//查单个
	Book selectOne(int bid);
	
	//查所有
	List<Book> selectAll();
}

BookDaoImpl类(实现BookDao接口)

package cn.bdqn.dao.lmpl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import cn.bdqn.dao.BookDao;
import cn.bdqn.entity.Book;
import cn.bdqn.utils.DBUtils;

public class BookDaoImpl implements BookDao {

	//全局变量
	PreparedStatement preS=null;
	Connection connection;
	
	@Override
	public int insert(Book book) {
		
		//获取链接
		connection=DBUtils.getConnection();
		String sql="insert into book(isbn,name,author,press,price,classification) values(?,?,?,?,?,?);";
		
		try {
			preS=connection.prepareStatement(sql);
			// 绑定参数
//			preS.setInt(1, book.getBid());
			preS.setString(1, book.getIsbn());
			preS.setString(2, book.getName());
			preS.setString(3, book.getAuthor());
			preS.setString(4, book.getPress());
			preS.setDouble(5, book.getPrice());
			preS.setString(6, book.getClassification());
			
			return preS.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			DBUtils.closeAll(null, preS, null);
		}		
		return 0;
	}

	@Override
	public int delete(int bid) {
		//获取链接
		connection = DBUtils.getConnection();
		String sql = "delete from book where bid = ?;";
		
		try {
			preS = connection.prepareStatement(sql);
			// 绑定参数
			preS.setInt(1, bid);
			
			return preS.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(null, preS, null);
		}
		return 0;
	}

	@Override
	public int update(Book book) {
		//获取链接
		connection = DBUtils.getConnection();
		String sql = "update book set isbn = ?,name = ?, author= ?,press = ?,price = ?,classification = ? where bid=?;";

		try {
			preS = connection.prepareStatement(sql);
			// 绑定参数
			preS.setString(1, book.getIsbn());
			preS.setString(2, book.getName());
			preS.setString(3, book.getAuthor());
			preS.setString(4, book.getPress());
			preS.setDouble(5, book.getPrice());
			preS.setString(6, book.getClassification());
			preS.setInt(7, book.getBid());

			return preS.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(null, preS, null);
		}
		return 0;
	}

	@Override
	public Book selectOne(int bid) {
		ResultSet resultSet = null;
		Book book = null;

		//获取连接
		connection = DBUtils.getConnection();
		String sql = "select * from book where bid = ?";

		try {
			preS = connection.prepareStatement(sql);

			// 绑定参数
			preS.setInt(1, bid);
			resultSet = preS.executeQuery();

			if (resultSet.next()) {
				book=new Book(bid, resultSet.getString(2), resultSet.getString(3),resultSet.getString(4)
						,resultSet.getString(5),resultSet.getDouble(6),resultSet.getString(7));
			}

			return book;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(resultSet, preS, null);
		}
		return null;
	}

	@Override
	public List<Book> selectAll() {
		ResultSet resultSet = null;
		Book book = null;
		List<Book> bookList = new ArrayList<Book>();

		//获取连接
		connection = DBUtils.getConnection();
		String sql = "select * from book";

		try {
			preS = connection.prepareStatement(sql);
			resultSet = preS.executeQuery();

			while (resultSet.next()) {
				book=new Book(resultSet.getInt(1), resultSet.getString(2), resultSet.getString(3),resultSet.getString(4)
						,resultSet.getString(5),resultSet.getDouble(6),resultSet.getString(7));
				bookList.add(book);
			}

			return bookList;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(resultSet, preS, null);
		}
		return null;
	}

}

服务层Service层

  Service层叫服务层,被称为服务,粗略的理解就是对一个或多个DAO进行的再次封装,封装成一个服务,所以这里也就不会是一个原子操作了,需要事物控制。

BookService接口

package cn.bdqn.service;

import java.util.List;

import cn.bdqn.entity.Book;

public interface BookService {

	//添加图书
	int addBook(Book book);
	
	//删除图书
	int deleteBook(int bid);
	
	//修改图书
	int updateBook(Book book);
	
	//查询一本图书
	Book selectOne(int bid);
	
	//查询所有图书
	List<Book> selectAll();
}

BookServiceImpl类(实现BookService接口)

package cn.bdqn.service.Impl;

import java.util.List;

import cn.bdqn.dao.lmpl.BookDaoImpl;
import cn.bdqn.entity.Book;
import cn.bdqn.service.BookService;

public class BookServiceImpl implements BookService {

	// 定义PeopleDaoImpl对象
	BookDaoImpl bookDaoImpl = new BookDaoImpl();

	@Override
	public int addBook(Book book) {
		int num=bookDaoImpl.insert(book);
		return num;
	}

	@Override
	public int deleteBook(int bid) {
		int num=bookDaoImpl.delete(bid);
		return num;
	}

	@Override
	public int updateBook(Book book) {
		int num=bookDaoImpl.update(book);
		return num;
	}

	@Override
	public Book selectOne(int bid) {
		Book book=bookDaoImpl.selectOne(bid);
		return book;
	}

	@Override
	public List<Book> selectAll() {
		List<Book> bookList=bookDaoImpl.selectAll();
		return bookList;
	}
}

视图层View层

TestBookServiceImpl测试类

package cn.bdqn.view;
import java.util.List;
import cn.bdqn.entity.Book;
import cn.bdqn.service.Impl.BookServiceImpl;

public class TestBookServiceImpl {

	public static void main(String[] args) {

		// 创建BookServiceImpl对象
		BookServiceImpl bookServiceImpl = new BookServiceImpl();

		// 增
		Book book = new Book("977-8-3154-6587-3", "jQuery从入门到精通", "王五",
				"北京大学出版社", 88.88, "前端开发");
		if (bookServiceImpl.addBook(book) != 0) {
			System.out.println("图书添加成功!");
		}
		
		// 删
		if (bookServiceImpl.deleteBook(1001)!= 0) {
			System.out.println("图书删除成功!");
		}
		
		//改
		Book book1 = new Book(1003, "977-8-3154-6587-4", "jQuery从入门到精通", "王六",
				"北京大学出版社", 88.88, "前端开发");
		if (bookServiceImpl.updateBook(book1)!= 0) {
			System.out.println("图书修改成功!");
		}
		
		//查
		if(bookServiceImpl.selectOne(1002)!=null)
		{
			System.out.println("图书查询成功!图书信息为:"+bookServiceImpl.selectOne(1002).toString());
		}
		
		//查所有
		List<Book> bookList=bookServiceImpl.selectAll();
		if(bookList.size()>0){
			System.out.println("查询到所有图书为:");
			for (Book book2 : bookList) {
				System.out.println(book2);
			}
		}
		
	}
}

完整代码

book表的三层架构完整代码

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Security(1)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 虽然说互联网是一个非常开发、几乎没有边界的信息大海&#xff0c;但说起来有点奇怪的是&#xff0c;每个稍微有点规模的互联网应用都有自己的权限系统&#xff…

BSV 上的 PLONK

我们很自豪地宣布 BSV 现在支持 PLONK。关于 PLONK 工作原理的详细说明&#xff0c;可以参考我们之前的解释 第一部分 和 第二部分。 我们之前已经实现了 Groth16&#xff0c;这是最小且最高效的 SNARK 构造。但是&#xff0c;它需要为每个电路进行可信设置。通过消除对每条电…

算法工程师应该熟知的C++高级用法

1. lambda表达式&#xff08;C11&#xff09; 1.1 lambda表达式的组成 []/*1*/ ()/*2*/ mutable/*3*/ throw()/*4*/ -> int/*5*/ {}/*6*/capture子句参数列表(optional)可变规范(optional)异常定义(optional)返回类型(optional)函数体 1.2 即看即用 语法&#xff1a; […

我现在是如何听歌的?

个人听歌需求 首先讲下个人听歌的情况&#xff0c;再讲讲我是怎么解决自己的听歌需求的&#xff0c;不一定适合所有人&#xff0c;但多少有点启发。我个人听歌的特殊需求其实还蛮多的。 比如&#xff1a; 突然会想单曲循环一首歌&#xff0c;直到耳朵说够了。 喜欢组装各种歌…

小啊呜产品读书笔记001:《邱岳的产品手记-06》第13讲 无用却必要:产品规划【上】 第14讲 留白与节奏:产品规划【下】

小啊呜产品读书笔记001&#xff1a;《邱岳的产品手记-06》第13讲 无用却必要&#xff1a;产品规划【上】 & 第14讲 留白与节奏&#xff1a;产品规划【下】一、今日阅读计划二、泛读&知识摘录1、第13讲 无用却必要&#xff1a;产品规划【上】2、第14讲 留白与节奏&#…

数据中心网络是什么?如何管理数据中心网络

什么是数据中心网络 数据中心网络是提供网络、存储和计算资源&#xff0c;为企业/企业数据中心租户执行广泛的工作负载。这些工作负载需要不同的硬件或高端网络组件来计算、存储、检索和传输来自本地和广域网的工作负载中的数据。 数据中心网络的核心支柱 在数据中心网络架构…

【第四部分 | JavaScript 基础】2:运算、控制流程、数组

目录 | 运算符 概述 浮点数有精度误差 自增和自减 比较运算符 逻辑运算符 赋值运算符 运算优先级 | 流程控制 条件判断 if、if...else 三元表达式 分支语句 switch | 循环 | 断点调试 | 数组 创建数组 访问与遍历 获取数组长度 JavaScript的数组 和 Java 的区…

LabVIEW项目中实时目标出现黄色感叹号

LabVIEW项目中实时目标出现黄色感叹号 当打开一个包含实时目标的LabVIEW项目&#xff08;如CompactRIO&#xff08;cRIO&#xff09;、CompactDAQ&#xff08;cDAQ&#xff09;或实时PXI&#xff09;时&#xff0c;在目标旁边看到一个黄色感叹号。单击目标时&#xff0c;收到以…

目标检测论文解读复现之十四:一种基于残差网络优化的航拍小目标检测算法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

代码随想录算法训练营第六天|字符串 栈 队列

字符串 字符串是我的弱点&#xff0c;主要是函数用的不是很熟练 注意因为字符串是左闭右开区间&#xff0c;而且字符串末尾还有一个"/0"&#xff0c;所以我们在reverse的时候是 [s.begin(),s.begin() len] 其中len是string的长度&#xff0c;假如string的长度是6…

[Nacos][Rancher][微服务] 容器化Docker部署的Nacos拒接连接

问题 2022-11-21 16:16:37.836 |-ERROR [main] com.alibaba.nacos.client.naming [552] -| request: /nacos/v1/ns/instance failed, servers: [localhost:8848], code: 500, msg: Connection refused (Connection refused) 2022-11-21 16:16:37.837 |-ERROR [main] com.ali…

Move 学习记录

Move在线IDE Move Playground 基本数据类型 只包括 无符号整型、布尔型、地址 3种类型&#xff0c;没有像其它语言中有字符串类型。 数据类型数据类型表示符号无符号整型u8, u64, u128布尔类型bool地址类型address&#xff0c; ex: Std, 0x1, Sender 变量定义&#xff08;4…

应急响应-文件痕迹排查

文件痕迹排查文件痕迹排查Windows文件痕迹排查敏感目录时间点文件排查Linux文件痕迹排查敏感目录时间点排查特殊文件文件痕迹排查 在应急响应排查的过程中&#xff0c;由于大部分的恶意软件、木马、后门等都会在文件维度上留下痕迹&#xff0c;因此对文件痕迹的排查必不可少。…

【数据挖掘】关联规则挖掘

关联规则挖掘 一、基本概念 概念 关联规则挖掘(Association rules mining) 在数据集中找到各项数据之间的关联关系。 项目(Item) IDItems bought10A,B,D20A,C,D30A,D,E 支持度(support) 项集{x,y}\{x,y\}{x,y}在总项集中出现的概率(x,yx,yx,y同时出现) Support(x→y)P(x,…

使用ESP32连接腾讯云实现远程控制方法

​大家好&#xff0c;上次给大家分享了如何使用ESP32实现蓝牙通信&#xff0c;今天跟大家聊聊如何使用ESP32连接腾讯云实现远程控制。本次实验用到MQTT协议&#xff0c;同样&#xff0c;我用miropython编写程序实现&#xff0c;最终可以通过腾讯连连微信小程序添加设备来发布主…

【GamePlay】两个ScrollView插件,Super ScrollView UIExtensions

前言 记录一下最近了解使用的两个滚动列表插件&#xff0c;UIExtensions 和Super ScrollView 。 原生的ScrollView 只能滚动 Viewport中Content范围内的物体&#xff0c;如果要使用必须得做一些功能扩展&#xff0c;很不方便&#xff0c;于是找了这两个插件。 前者不只是滚动…

一文了解JVM整体设计

一、JDK / JRE / JVM二、.Java 文件运行过程三、JVM运行时数据区3.1 Method Area3.2 Heap3.3 Java Virtual Machine Stacks3.4 Native Method Stacks3.5 The PC Register四、JVM内存模型4.1 JVM对象创建和回收过程五、垃圾收集5.1 确定垃圾收集对象5.1.1 引用计数法5.1.2 可达性…

2023年英语二大作文押题猜想(达立易考)

又到了考前大开脑洞的时间了&#xff01;每年一到这个时间点&#xff0c;关于押题猜题的话题就会铺天盖地而来&#xff0c;众多名师大咖更是会集毕生所学&#xff0c;期待可以在这个环节押中部分题目彰显实力&#xff0c;其中主观题就是大家集中关注的重要热点模块。押题听起来…

声纹识别开源工具 ASV-Subtools

今天非常荣幸有机会在Speechhome语音技术研讨会上分享我们团队在开源项目上的一些工作。今天我分享的主题是声纹识别开源工具ASV-Subtools。 今天我分享的主要有5个部分的内容&#xff0c;分别是背景介绍、工具介绍、实验结果、Subtools工程化、总结与展望。其中Subtools工程化…

【ROS】机械人开发五--ROS基本概念的程序实现

机械人开发五--ROS基本概念的程序实现一、开发工具二、RoboWare Studio的基本使用2.1 软件启动2.2 修改界面语言2.3 使用2.4 编译文件2.5 卸载三、话题通信四、话题的代码编写4.1 发布端4.2 接收端4.3 测试五、自定义消息5.1 自定义消息类型5.2 自定义消息发布端5.3 自定义消息…