今天接继续学习JDBC,其中今天最关键的就是如何封装BaseDao
先串一下分层的具体步骤 : ----BaseDao具体实现在下面
1.新建Java项目,并添加数据库的驱动包
2.新建常用的包
com.sxt.commons :工具类
com.sxt.dao :数据访问接口
com.sxt.dao.impl:数据访问接口的实现类
com.sxt.pojo:实体类
com.sxt.service:服务层,业务逻辑接口
com.sxt.service.impl:业务逻辑实现类
com.sxt.test:测试类
3.在com.sxt.pojo包下添加实体类,封装与数据表相关的数据(实体类的类名与表名相同,属性名称与表的字段相同)
public class Student {
private String scode;//学号
private String sname;//名称
private int age;
private float score;
..省略getter和setter方法
}
4.编写DAO接口(表名+Dao)及其实现类(表名+DaoImpl)
a.StudentDao接口 ---没有方法体的方法,需要StudentDaoImpl实现类来来实现它
public interface StudentDao {
/**
* 新增学生
*/
public int addStudent(Student student);
/**
* 修改学生
*/
public int updateStudent(Student student);
/**
* 删除学生
*/
public int deleteStudent(String scode);
/**
* 查询所有学生
*/
public List<Student> findAll();
/**
* 根据学生编号查询学生详情
*/
public Student findByScode(String scode);
}
b.新建StudentDaoImpl
package com.sxt.dao.impl;
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 com.sxt.commons.JdbcUtil;
import com.sxt.dao.StudentDao;
import com.sxt.pojo.Student;
public class StudentDaoImpl implements StudentDao {
//新增语句
@Override
public int addStudent(Student student) {
int count = 0;
String sql="insert into student(scode,sname,age,score) values(?,?,?,?)";
Connection conn=null;
PreparedStatement psmt = null;
conn = JdbcUtil.getConnection();
try {
psmt = conn.prepareStatement(sql);
//为占位符绑定值
psmt.setString(1, student.getScode());
psmt.setString(2, student.getSname());
psmt.setInt(3, student.getAge());
psmt.setFloat(4, student.getScore());
//执行新增
count = psmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn, psmt, null);
}
return count;
}
//修改语句
@Override
public int updateStudent(Student student) {
int count = 0;
String sql="update student set sname=?,age=?,score=? where scode=?";
Connection conn=null;
PreparedStatement psmt = null;
conn = JdbcUtil.getConnection();
try {
psmt = conn.prepareStatement(sql);
//为占位符绑定值
psmt.setString(1, student.getSname());
psmt.setInt(2, student.getAge());
psmt.setFloat(3, student.getScore());
psmt.setString(4, student.getScode());
//执行新增
count = psmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn, psmt, null);
}
return count;
}
//删除语句
@Override
public int deleteStudent(String scode) {
int count = 0;
String sql="delete from student where scode=?";
Connection conn=null;
PreparedStatement psmt = null;
conn = JdbcUtil.getConnection();
try {
psmt = conn.prepareStatement(sql);
//为占位符绑定值
psmt.setString(1, scode);
//执行新增
count = psmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn, psmt, null);
}
return count;
}
//查询语句
@Override
public List<Student> findAll() {
List<Student> list = new ArrayList<>();
String sql="select * from student";
Connection conn=null;
PreparedStatement psmt = null;
ResultSet rs = null;
conn = JdbcUtil.getConnection();
try {
psmt = conn.prepareStatement(sql);
//执行查询
rs = psmt.executeQuery();
while(rs.next()){
//创建Student对象用于封装一条记录的数据
Student student = new Student();
student.setScode(rs.getString("scode"));
student.setSname(rs.getString("sname"));
student.setAge(rs.getInt("age"));
student.setScore(rs.getFloat("score"));
list.add(student);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn, psmt, rs);
}
return list;
}
//查询单条语句
@Override
public Student findByScode(String scode) {
String sql="select * from student where scode=?";
Connection conn=null;
PreparedStatement psmt = null;
ResultSet rs = null;
conn = JdbcUtil.getConnection();
Student student = null;
try {
psmt = conn.prepareStatement(sql);
psmt.setString(1, scode);
//执行查询
rs = psmt.executeQuery();
while(rs.next()){
//创建Student对象用于封装一条记录的数据
student = new Student();
student.setScode(rs.getString("scode"));
student.setSname(rs.getString("sname"));
student.setAge(rs.getInt("age"));
student.setScore(rs.getFloat("score"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn, psmt, rs);
}
return student;
}
}
5.服务层(业务逻辑层),调用DAO完成业务逻辑。新建Service接口(表名+Service)及其Service接口的实现类(表名+ServiceImpl),
(13)通过 PreparedStatement 对象完成数据的查询
(13.1)查询返回单条结果集
(13.2)查询返回多条结果集
在条件是like时%号该如何定义
一定要注意%本来就是属于条件的一部分,应该将其和值放在一起,然后绑定到问号中
不要在语句中定义%?%,再往%里绑值.这样会导致结果出错
(14)PreparedStatement 批处理操作
批处理:在与数据库的一次连接中,批量的执行条 SQL 语句
如何更加高效的一次性插入多条数据?
有两种方式:一种,把写好的插入数据的方法在循环中调用10次,另一种,新写一种方法,在建立一次Connection连接中完成十条数据的添加
第一种方法性能极其低下,需要创建十次连接,对象,关闭等操作.非常麻烦
添加批处理时会出现
(15)JDBC中的事务处理
在JDBC中操作数据中数据库事务默认为自动提交,如果事务改为手动提交,我们需要使用
Connection对象中的setAutoCommit 方法来关闭事务自动提交。然后通过
Connection 对象中的 commit 方法与 rollback 方法进行事务的提交与回滚。
4 JDBC 进阶
(1)动态查询
动态查询:根据用户给定的条件来决定执行什么样的查询。
(2)应用程序分层
(2.1)应用程序分层是什么
应用程序通过创建不同的包来实现项目的分层,将项目中的代码根据功能做具体划分,并存放在不同的包下
(2.2)分层优点
1、分层结构将应用系统划分为若干层,每一层只解决问题的一部分,通过各层的协作提供整体解决方案。
2、分层结构具有良好的可扩展性,为应用系统的演化增长提供了一个灵活的支持,具有良好的可扩展性。
3、分层架构易于维护。
(2.3)三层结构
三层结构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层
(Business Logic Layer)、数据访问层(Data access layer)。
分层的目的是为了:"高内聚低 耦合"的思想
(2.4)项目分层
在持久层里起名称时不要包含业务,这样持久层的复用性就会更高
添加项目分层时,有时会自动过滤创建的空包,比如:让com.sxt.Dao空包显示出来要点击
3 封装通用的 BaseDao
封装工具包JDBCUtil: ----最上面的impl实现类中代码会有很多重复,下面就是改进方法
持久层(数据访问层)---StudentDao接口和StudentDaoImpl实现类
StudentDaoImpl