1、jdbc.properties配置文件

jdbc.properties

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/animedb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
user=root
password=root

2、JDBCUtil 工具类

JDBCUtil.java

package com.kgc.jdbc;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties; /**
* JDBC数据库操作工具类-都是公共的静态方法(不需要实例化),减少代码冗余
* @author zhukang
*
*/
public class JDBCUtil { /**
* 读取外部的数据库连接信息配置文件,获取数据库连接对象
*/
public static Connection getConnection() throws Exception { // 创建Properties属性对象
Properties properties = new Properties(); // 使用反射机制,读取外部配置文件
InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); // 加载输入流对象,获取配置文件内容
properties.load(inputStream); // 读取数据库连接信息
String driverClass = properties.getProperty("driverClass");
String jdbcUrl = properties.getProperty("jdbcUrl");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); // 加载驱动
Class.forName(driverClass); // 获取数据库连接对象
return DriverManager.getConnection(jdbcUrl, user, password);
} /**
* 增删改的通用方法:只需要提供执行的SQL语句和SQL语句需要的参数,使用预处理对象
*/
public static int update(String executeSql, Object ... params){ // 定义数据库连接和预处理操作对象
Connection conn = null;
PreparedStatement pstmt = null; // 定义SQL语句执行的影响行数
int row = 0; // 公共执行增删改的处理代码
try {
// 获取数据库连接
conn = getConnection(); // 创建预处理操作对象
pstmt = conn.prepareStatement(executeSql); // 实现动态传参,注意: 传入的预编译SQL的?和传入的参数个数和顺序要一致,即:要保证一一对应
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
} // 执行增删改操作,并获取影响行数
row = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseResource(conn, pstmt, null);
} // 返回影响行数
return row; } /**
* 查询的通用方法:只需要提供执行的SQL语句和SQL语句需要的参数,使用预处理对象
*/
public static ResultSet select(String executeSql, Object ... params){ // 定义数据库连接,预处理操作对象,结果集对象
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null; // 公共执行查询的处理代码
try {
// 获取数据库连接
conn = getConnection(); // 创建预处理操作对象
pstmt = conn.prepareStatement(executeSql); // 实现动态传参,注意: 传入的预编译SQL的?和传入的参数个数和顺序要一致,即:要保证一一对应
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
} // 执行查询操作,并获取结果集
rs = pstmt.executeQuery();
} catch (Exception e) {
e.printStackTrace();
} finally {
//最好不释放资源,因为rs要返回,关闭后,直接外层不可以使用
releaseResource(conn, pstmt, rs);
} // 返回查询结果集
return rs; } /**
* 释放数据库操作对象资源
*/
public static void releaseResource(Connection conn, Statement stmt, ResultSet rs){
try {
// 手动释放
if (null != rs) {
rs.close();
} if (null != stmt) {
stmt.close();
} if (null != conn) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} }

3、作业总结技巧 (JdbcUtil 页面跳转 Jstl)

这些只是我个人的思考,可能会比较冗余,我是为了多思考,记录当时的感受;

且以访问资源为主和jstl,后面的以Ajax为主;

3.1Jstl妙用 (基于 Jstl遍历数据添加元素)

3.1 类型cid->类型名 显示数据时 外键信息对应

animesList:为动漫list集合的数据,放在request域中;

categoriesList:为动漫的类型,放在session域中(主要是因为方便修改和添加的时候方便获取类型);

外层循环,遍历每条动漫数据,内层循环,查询动漫对应的类型名称;

<!--
animesList:为动漫list集合的数据,放在request域中;
categoriesList:为动漫的类型,放在session域中(主要是因为方便修改和添加的时候方便获取类型)
外层循环,遍历每条动漫数据,内层循环,查询动漫对应的类型名称
-->
<c:forEach items="${animesList}" var ="anime" varStatus="status">
<!-- 遍历动漫的cid -->
<c:forEach items="${categoriesList}" var ="category" varStatus="status">
<!-- 根据动漫的cid 与 类型的id 匹配对应的动漫类型 -->
<c:if test="${ anime.cid eq category.id}" var="flag">
${category.name}
</c:if>
</c:forEach>
</c:forEach>

3.2 类型cid->类型名 修改数据时 外键信息对应

修改动漫数据,跳修改页面后显示数据,类型可以选择并且,选择了以前的类型selected="selected"

<!-- 修改动漫数据,跳修改页面后显示数据,类型可以选择并且,选择了以前的类型selected="selected" -->
<select name="cid" id="categories">
<!-- 动漫类型 将数据放进session中然后直接通过Jstl表达式遍历 -->
<c:forEach items="${categoriesList}" var ="category" varStatus="status">
<option value="${category.id }"
<c:if test="${ upAnimes.cid eq category.id}" var="flag">
selected="selected"
</c:if>
>${category.name }</option>
</c:forEach>
</select>

3.2.response 返回弹窗,并跳转

直接在返回中写javaScript;

resp.getWriter().print("<script type='text/javascript'>alert('删除成功!!!'); location.href = 'animes'</script>");

3.3 getPartment(str) 再次理解

如果属性,没有参数就是空字符串“” ,如果没有属性,获取的就是null

getPartment(str); //如果属性,没有参数就是空字符串“”  ,如果没有属性,获取的就是null
getPartment(str).trim(); //防止不小心多输入空格,去掉前后的空格,但是 trim()必须保证参数值不为 null

3.4 模糊 sql拼接

like concat(''%,?,'%') 方便模糊查询

sql拼接及 Object数组 数组动态添加参数的弊端(后面使用List集合添加数组,最后在转成数组)

//注意这种参数判断的思想
//条件查询动漫
public List<Animes> searchAnimes(Search search) throws SQLException{
List<Animes> animesList = new ArrayList<>(); String executeSql = "select `id`,`cid`,`name`,`author`,`actor`,`produce`,`create_date` from animes";
//参数
Object[] params = {}; //如果有参数
if(!"".equals(String.valueOf(search.getAnimeName())) || !"".equals(String.valueOf(search.getAnimeAuthor())) || !"0".equals(String.valueOf(search.getAnimeCategory()))) {
executeSql = executeSql.concat(" where");
} //如果有动漫名
if(!"".equals(String.valueOf(search.getAnimeName()))) {
executeSql = executeSql.concat(" name like concat('%',?,'%')");
Object[] params1 = {search.getAnimeName()};
params = params1;
} //如果有动漫名 和作者
if(!"".equals(String.valueOf(search.getAnimeName())) && !"".equals(String.valueOf(search.getAnimeAuthor()))) {
executeSql = executeSql.concat(" and author like concat('%',?,'%')");
Object[] params2 = {search.getAnimeName(),search.getAnimeAuthor()};
params = params2;
}else if(!"".equals(String.valueOf(search.getAnimeAuthor()))){
//如果 作者
executeSql = executeSql.concat(" author like concat('%',?,'%')");
Object[] params3 = {search.getAnimeAuthor()};
params = params3;
} //如果有 作者名 和 动漫名 和 类型
if(!"".equals(String.valueOf(search.getAnimeName())) && !"".equals(String.valueOf(search.getAnimeAuthor())) && !"0".equals(String.valueOf(search.getAnimeCategory()))) {
executeSql = executeSql.concat(" and cid = ?");
Object[] params4 = {search.getAnimeName(),search.getAnimeAuthor(),search.getAnimeCategory()};
params = params4;
}else if(!"".equals(String.valueOf(search.getAnimeName())) && !"0".equals(String.valueOf(search.getAnimeCategory()))) {
//动漫名 和 类型
executeSql = executeSql.concat(" and cid = ?");
Object[] params5 = {search.getAnimeName(),search.getAnimeCategory()};
params = params5;
}else if(!"".equals(String.valueOf(search.getAnimeAuthor())) && !"0".equals(String.valueOf(search.getAnimeCategory()))) {
//作者 和 类型
executeSql = executeSql.concat(" and cid = ?");
Object[] params6 = {search.getAnimeAuthor(),search.getAnimeCategory()};
params = params6;
}else if(!"0".equals(String.valueOf(search.getAnimeCategory()))){
//类型
executeSql = executeSql.concat(" cid = ?");
Object[] params7 = {search.getAnimeCategory()};
params = params7;
} System.out.println("searchAnimes 搜索的SQL==>"+executeSql); ResultSet rs = JDBCUtil.select(executeSql, params); while(rs.next()) {
Animes anime = new Animes();
anime.setId(rs.getInt("id"));
anime.setCid(rs.getInt("cid"));
anime.setName(rs.getString("name"));
anime.setAuthor(rs.getString("author"));
anime.setActor(rs.getString("actor"));
anime.setProduce(rs.getString("produce"));
anime.setCreate_date(rs.getDate("create_date"));
animesList.add(anime);
}
System.out.println("----- AnimesImpl 遍历数据库中查询的数据 ----");
for (int i = 0; i < animesList.size(); i++) {
System.out.println(animesList.get(i).toString());
}
System.out.println("----- AnimesImpl 遍历数据库中查询的数据结束 ---"); return animesList; }

3.5 标记 搜索关键字

在数据查询的时候将关键字进行替换 replace(oldstr,new str);

//标记关键字 name
String markName = "replace(`name`,'"+search.getAnimeName() +"',\"<span style='color:red'>"+search.getAnimeName()+"</span>\") as 'name'";
//标记关键字 author
String markAuthor = "replace(`author`,'"+search.getAnimeAuthor() +"',\"<span style='color:red'>"+search.getAnimeAuthor()+"</span>\") as 'author'"; //执行的sql
String executeSql = "select `id`,`cid`,"+markName+","+markAuthor+",`actor`,`produce`,`create_date` from animes";

3.6 分页查询

//分页查询所有的动漫数据
public List<Animes> pageSelectAllAnimes(PageUtil pageUtil) throws SQLException{
List<Animes> animesList = new ArrayList<>(); String executeSql = "select `id`,`cid`,`name`,`author`,`actor`,`produce`,`create_date` from animes limit ?,?"; //参数
Object[] params = {(pageUtil.getPageNum()-1)*pageUtil.getPageSize(),pageUtil.getPageSize()}; ResultSet rs = JDBCUtil.select(executeSql, params); while(rs.next()) {
Animes anime = new Animes();
anime.setId(rs.getInt("id"));
anime.setCid(rs.getInt("cid"));
anime.setName(rs.getString("name"));
anime.setAuthor(rs.getString("author"));
anime.setActor(rs.getString("actor"));
anime.setProduce(rs.getString("produce"));
anime.setCreate_date(rs.getDate("create_date"));
animesList.add(anime);
}
System.out.println("----- AnimesImpl 打印测试 当前页=》"+pageUtil.getPageNum()+",页面大小=》"+pageUtil.getPageSize());
for (int i = 0; i < animesList.size(); i++) {
System.out.println(animesList.get(i).toString());
}
System.out.println("-----------------------------------"); return animesList;
}

3.7 分页工具类

//分页工具类
public class PageUtil { //一共多少条数据
private int dateCount;
//每页显示的数据条数
private int pageSize = 5;
//当前页
private int pageNum = 1;
//最大页数
private int maxPageNum; //构造方法,需要 数据量 和 页面大小
public PageUtil(int dateCount) {
this.dateCount = dateCount;
this.maxPageNum = (this.dateCount%pageSize) == 0 ? (this.dateCount/pageSize) : (this.dateCount/pageSize) +1 ;
} //获取当前页面
public int getPageNum() {
return pageNum;
} //设置当前页面
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
} //获取最大页面数
public int getMaxPageNum() {
return this.maxPageNum;
} //获取页面大小
public int getPageSize() {
return pageSize;
} //设置页面大小
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
//页面大小切换后应该重新切换页面数量
this.maxPageNum = (this.dateCount%pageSize) == 0 ? (this.dateCount/pageSize) : (this.dateCount/pageSize) +1 ;
} //获取数据总条数
public int getDateCount() {
return dateCount;
} }

3.8 获取select的值 change()事件动态获取pageSize 并拼接参数

select标签的change()事件, 切换选项时触发;

<!-- href拼接pageSize -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js" ></script>
<script type="text/javascript">
$(function(){
//获取页面大小
let pageSize = $("#pageSize").val(); //加载页面先拼接页面
$(".pagea").each(function(){
let oldhref = $(this).attr("href").substr(0,30);
let newhref = oldhref + pageSize;
//alert(newhref);
$(this).attr("href",newhref);
}); //修改pageSize
//select标签的change()事件, 切换选项时触发
$("#pageSize").change(function(){
pageSize = $("#pageSize option:selected").val();
//alert(pageSize);
//修改后的pageSize
$(".pagea").each(function(){
let oldhref = $(this).attr("href").substr(0,30);
let newhref = oldhref + pageSize;
//alert(newhref);
$(this).attr("href",newhref);
}); //根据新的pageSize跳转
//alert(pageSize);
//跳转的新页面
//alert("pageSearch?pageNum=1&amp&pageSize="+pageSize);
location.href = "pageSearch?pageNum=1&amp&pageSize="+pageSize;
}); }); </script>

跳转页面的链接 首页,上一页,下一页,尾页

<!-- pageNum 当前页 -->
<a href="pageSearch?pageNum=1&pageSize=" class="pagea">首页</a>&nbsp;|&nbsp;
<c:if test="${pageUtil.pageNum ne 1}" var="sexFlag">
<a href="pageSearch?pageNum=${pageUtil.pageNum -1 }&pageSize=" class="pagea">&lt;&lt;上一页</a>&nbsp;|&nbsp;
</c:if>
<c:if test="${pageUtil.pageNum ne pageUtil.maxPageNum}" var="sexFlag">
<a href="pageSearch?pageNum=${pageUtil.pageNum +1 }&pageSize=" class="pagea">下一页&gt;&gt;</a>&nbsp;|&nbsp;
</c:if>
<a href="pageSearch?pageNum=${pageUtil.maxPageNum }&pageSize=" class="pagea">尾页</a>&nbsp;|&nbsp;

3.9 动态显示pageSize

<!-- 动态显示pageSize
pageSizeList 为 PageSize 对象集合 PageSize 对象只有一个 String pageSize 页面大小属性
-->
<select name="pageSize" id="pageSize">
<!--页面大小 pageSize -->
<c:forEach items="${pageSizeList}" var ="pageSize" varStatus="status">
<option value="${pageSize.pageSize}"
<c:if test="${pageUtil.pageSize eq pageSize.pageSize}">
selected = "selected"
</c:if>
>${pageSize.pageSize}</option>
</c:forEach>
</select>

3.10 登录 AnimeServlet 第一次跳转到展示页面 需要准备一些数据

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //======从数据库获取动漫数据 不走条件查询======
List<Animes> animesList = new ArrayList<>();
AnimesImpl animesImpl = new AnimesImpl();
// try {
// animesList = animesImpl.selectAllAnimes();
// } catch (SQLException e) {
// e.printStackTrace();
// } //======从数据库获取动漫数据 走条件查询======
//获取动漫的总条数
int dateCount = 0;
try {
dateCount = animesImpl.selectAllAnimesCounts();
} catch (SQLException e) {
e.printStackTrace();
} PageUtil pageUtil = new PageUtil(dateCount);
//将分页对象放进session域中,初始化页面对象
req.getSession().setAttribute("pageUtil", pageUtil);
try {
animesList = animesImpl.pageSelectAllAnimes(pageUtil);
} catch (SQLException e) {
e.printStackTrace();
} //将动漫集合放入request中
req.setAttribute("animesList", animesList); //======动漫类型======
List<Category> categoriesList = new ArrayList<>();
CategoryImpl categoryImpl = new CategoryImpl(); try {
categoriesList = categoryImpl.selectAllCategories();
} catch (SQLException e) {
e.printStackTrace();
}
//将类型数据放进session中
req.getSession().setAttribute("categoriesList", categoriesList); //页面大小
List<PageSize> pageSizeList = new ArrayList<PageSize>();
pageSizeList.add(new PageSize("3"));
pageSizeList.add(new PageSize("5"));
pageSizeList.add(new PageSize("10"));
pageSizeList.add(new PageSize("15"));
//将pageSize放进session中
req.getSession().setAttribute("pageSizeList", pageSizeList); System.out.println("==AnimeServlet 动漫数据条数"+dateCount+"当前页"+pageUtil.getPageNum()+"最大页"+pageUtil.getMaxPageNum()+"==="); //转发到动漫列表页面
req.getRequestDispatcher("web6Jdbc/animeListJson.jsp").forward(req, resp); }

3.11 分页Servlet->PageSelectAnimeServlet

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//第几页
int pageNum = Integer.parseInt(req.getParameter("pageNum")==null ? "1" :req.getParameter("pageNum"));
//页面大小
int pageSize = Integer.parseInt(req.getParameter("pageSize")==null ? "5" :req.getParameter("pageSize")); System.out.println("PageSelectAnimeServlet 当前页=》"+pageNum+",页面大小=》"+pageSize); AnimesImpl animesImpl = new AnimesImpl();
PageUtil pageUtil = null;
try {
//现在每次实例化都先获取数据总数,后面考虑更好的方法 ??小问题
pageUtil = new PageUtil(animesImpl.selectAllAnimesCounts());
} catch (SQLException e1) {
e1.printStackTrace();
}
pageUtil.setPageNum(pageNum);
pageUtil.setPageSize(pageSize); //每次分页查询要将分页工具类重新更新
req.getSession().setAttribute("pageUtil", pageUtil); List<Animes> animesList = new ArrayList<Animes>();
try {
animesList = animesImpl.pageSelectAllAnimes(pageUtil);
//将动漫集合放入request中
req.setAttribute("animesList", animesList);
} catch (SQLException e) {
e.printStackTrace();
} //转发到动漫列表页面
req.getRequestDispatcher("web6Jdbc/animeListJson.jsp").forward(req, resp); }

Javaweb06-JDBC的更多相关文章

  1. Java数据库连接技术——JDBC

    大家好,今天我们学习了Java如何连接数据库.之前学过.net语言的数据库操作,感觉就是一通百通,大同小异. JDBC是Java数据库连接技术的简称,提供连接各种常用数据库的能力. JDBC API ...

  2. 玩转spring boot——结合AngularJs和JDBC

    参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...

  3. [原创]java使用JDBC向MySQL数据库批次插入10W条数据测试效率

    使用JDBC连接MySQL数据库进行数据插入的时候,特别是大批量数据连续插入(100000),如何提高效率呢?在JDBC编程接口中Statement 有两个方法特别值得注意:通过使用addBatch( ...

  4. JDBC MySQL 多表关联查询查询

    public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver&q ...

  5. JDBC增加删除修改

    一.配置程序--让我们程序能找到数据库的驱动jar包 1.把.jar文件复制到项目中去,整合的时候方便. 2.在eclipse项目右击"构建路径"--"配置构建路径&qu ...

  6. JDBC简介

    jdbc连接数据库的四个对象 DriverManager  驱动类   DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 ...

  7. JDBC Tutorials: Commit or Rollback transaction in finally block

    http://skeletoncoder.blogspot.com/2006/10/jdbc-tutorials-commit-or-rollback.html JDBC Tutorials: Com ...

  8. FineReport如何用JDBC连接阿里云ADS数据库

    在使用FineReport连接阿里云的ADS(AnalyticDB)数据库,很多时候在测试连接时就失败了.此时,该如何连接ADS数据库呢? 我们只需要手动将连接ads数据库需要使用到的jar放置到%F ...

  9. JDBC基础

    今天看了看JDBC(Java DataBase Connectivity)总结一下 关于JDBC 加载JDBC驱动 建立数据库连接 创建一个Statement或者PreparedStatement 获 ...

  10. Spring学习记录(十四)---JDBC基本操作

    先看一些定义: 在Spring JDBC模块中,所有的类可以被分到四个单独的包:1.core即核心包,它包含了JDBC的核心功能.此包内有很多重要的类,包括:JdbcTemplate类.SimpleJ ...

随机推荐

  1. 124_Power Pivot&Power BI DAX优化计算最大连续次数

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 最大连续次数或者是最大连续子序列问题,在DAX中如何快速计算呢? 思路 1.N-1:按照INDEX错位 2.ST ...

  2. 花两万培训Java的三个同学,最后都怎么样了

    仙路尽头谁为峰,学完Java学Python. 前言 对于IT行业的培训,例如Java.大数据.H5等等,我一直保持着肯定的态度. 因为当年大学时期的我,也差点去参加Java培训.一是因为那时钱包空空, ...

  3. PostgreSQL Array 数组类型与 FreeSql 打出一套【组合拳】

    前言 PostgreSQL 是世界公认的功能最强大的开源数据库,除了基础数据类型 int4/int8/varchar/numeric/timestamp 等数据类型,还支持 int4[]/int8[] ...

  4. LVS+keepalived高可用

    1.keeplived相关 1.1工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题. 在一个LVS服务集群中通常有主服务器(MAS ...

  5. Java并发3

    轻量级锁:如果一个有多个线程访问,但多线程访问的时间是错开的,没有竞争,那么可以使用轻量级锁来优化: monitor:重量级锁: 正常我们使用synchronized时,没有竞争则是轻量级锁,当遇到竞 ...

  6. Java注释、标识符、关键字

    Java注释.标识符.关键字 注释 单行注释以"//" 开始:多行注释以 "/*" 开始,以"*/"结束:文档注释以 "/**&q ...

  7. 【spring源码系列】之【FactoryBean类型的接口】

    1.概述 目前我们知道,spring创建bean有多种方式,比如xml方式创建,比如@Component,@Service,@Controler,@Repository注解创建,比如@Autowire ...

  8. vue 封装弹窗组件注意

    父组件 <template> <div> <p @click="onDelete"> 打开 </p> <!-- 弹框 --&g ...

  9. 一种让运行在CentOS下的.NET CORE的Web项目简单方便易部署的自动更新方案

    一.项目运行环境 项目采用的是.NET5开发的Web系统,独立部署在省内异地多台CentOS服务器上,它们运行在甲方专网环境中(不接触互联网),甲方进行业务运作时(一段时间内)会要求异地服务器开机上线 ...

  10. Linux安装fastdfs集群部署

    过程问题: make: gcc:命令未找到 解决: yum -y install gcc 一.环境和版本: Linux环境:CentOS 7.6 libfastcommon版本:1.0.39 Fast ...