当前位置:网站首页>JDBC入门学习(二)之封装工具类
JDBC入门学习(二)之封装工具类
2022-06-23 03:55:00 【默主归沙】
- 工具类的封装(重点)
//问题: 每次进行CRUD操作,都要写一套JDBC,很繁琐
//解决方案:将重复的操作,抽取到工具类中封装
//1.加载驱动只需要一次---放到静态代码块
//问题2: 直接在工具类中将数据库驱动,数据库名,用户名,密码写死了,不方便后续变更---硬编码
//解决方案:需要变为软编码形式,使程序更灵活,维护性更强
public class LoginTest {
public static void main(String[] args) {
System.out.println("请输入用户名");
Scanner sc = new Scanner(System.in);
String username = sc.nextLine(); //获取一行内容
System.out.println("请输入密码");
String password = sc.nextLine();
if(login2(username,password)){
//登录功能
System.out.println("登录成功~!");
}else{
System.out.println("登录失败~!");
}
}
private static boolean login2(String username, String password) {
Connection conn = null;
PreparedStatement prst = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("select count(*) from user where username=? and password=?");
//参数1:对应第一个占位符? 下标从1开始
prst.setString(1,username);
prst.setString(2,password);
//获取结果集
//sql注入的隐患
rs = prst.executeQuery();
if(rs.next()){
int result = rs.getInt(1); //聚合函数只有一个字段
return result>0; //result不小于0,则返回true
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(rs,prst,conn);
}
return false;
}
private static boolean login(String username, String password) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
st = conn.createStatement();
//获取结果集
//sql注入的隐患
String sql = "select count(*) from user where username='"+username+"' and password='"+password+"'";
rs = st.executeQuery(sql);
if(rs.next()){
int result = rs.getInt(1); //聚合函数只有一个字段
return result>0; //result不小于0,则返回true
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(rs,st,conn);
}
return false;
}
}
public class DBUtils {
private static Properties p = new Properties();
//静态代码块:只加载一次
static{
//反射对象调用getResourceAsStream
//从src目录下获取到db.properties的资源
try {
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
p.load(is);
Class.forName(p.getProperty("driver"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("username"), p.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void closeAll(AutoCloseable...cs){
for(AutoCloseable c : cs){
if(c!=null){
try {
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
配置文件的抽取
在根目录自己创建一个db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///mydb1
username=root
password=123
- ORM (重点)
对象关系映射:对象-实体类(不放main方法的类),关系-数据表,两者数据的转换
简单地说,就是从数据表中取出数据后,存储到实体类中
//案例:获取岗位表的信息,存储到实体类中
//创建一个实体类与关系表对应: 对象属性=表字段
//将数据表中零散的字段值,封装到实体类中,方便操作
@Data //生成set/get及toString
@NoArgsConstructor //生成无参构造
@AllArgsConstructor //生成全参构造
class Jobs{
private String job_id;
private String job_title;
private String min_salary;
private String max_salary;
}
public class Test1 {
public static void main(String[] args) throws SQLException {
Connection conn = DBUtils.getConnection();
PreparedStatement prst = conn.prepareStatement("select * from t_jobs");
ResultSet rs = prst.executeQuery();
while(rs.next()){
String job_id = rs.getString("job_id");
String job_title = rs.getString("job_title");
String min_salary = rs.getString("min_salary");
String max_salary = rs.getString("max_salary");
Jobs jobs = new Jobs(job_id,job_title,min_salary,max_salary);
System.out.println(jobs); //对象关系映射:将表字段内容存到实体属性中
}
DBUtils.closeAll(rs,prst,conn);
}
}
- Dao层的抽取(重点)
Dao层:数据访问层,用于做与数据库交互的事情
如果不将dao层抽取,例如登录功能,所有代码都放到测试类中,使得测试类代码特别臃肿
抽取后代码分离设计:
main方法中做业务逻辑操作; dao层只做jdbc操作
案例: Person数据表的增删改查操作
创建数据表
> - 创建一张表 Person,有以下列:
> - id:int,主键,自动增长
> - name:varchar(20) 非空
> - age:int 非空
> - bornDate:Date
> - email:字符串
> - address:字符串
//在测试类中,进行业务逻辑操作
//操作步骤:
//1.创建数据表
//2.新建实体类
//3.编写工具类
//4.将jdbc抽象到dao层
//5.在测试类中编写业务逻辑
//------------创建实体类------------
//实体类中的属性要与表字段一致--ORM
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private int id;
private String name;
private int age;
private Date bornDate;
private String email;
private String address;
}
//------------创建测试类------------
public class Test1 {
public static void main(String[] args) {
System.out.println("请输入你要进行的操作:1.添加 2.修改 3 删除 4 查所有 5.根据id查");
PersonDaoImpl personDao = new PersonDaoImpl();
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
switch (num){
case 1: //添加传对象,一般主键自增长,id不用管
int result = personDao.insert(new Person(0,"ls",20,new Date(),"[email protected]","湖北"));
System.out.println("插入:"+result);
break;
case 2: //修改传对象,要有修改的主键id,才能修改
result = personDao.update(new Person(2,"ww",44,new Date(),"[email protected]","江西"));
System.out.println("修改:"+result);
break;
case 3:
result = personDao.delete(1); //删除id
System.out.println("删除:"+result);
break;
case 4: //查询所有,返回List集合
List<Person> list = personDao.selectAll();
System.out.println("查所有:"+list);
break;
case 5: //查询单个,往往根据id查,返回实体对象
Person person = personDao.selectById(2);
System.out.println("查对象:"+person);
break;
default:
System.out.println("您的输入有误~");
break;
}
}
}
//------------创建dao层操作------------
//dao层--数据访问层(用于做jdbc操作)
public class PersonDaoImpl {
public int insert(Person person) {
Connection conn = null;
PreparedStatement prst = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("insert into person(name,age,bornDate,email,address) values(?,?,?,?,?)");
prst.setString(1,person.getName());
prst.setInt(2,person.getAge());
//sql包下的new Date(参数)可以long类型的毫秒值参数
prst.setDate(3,new Date(person.getBornDate().getTime()));
prst.setString(4,person.getEmail());
prst.setString(5,person.getAddress());
return prst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(prst,conn);
}
return 0;
}
public int update(Person person) {
Connection conn = null;
PreparedStatement prst = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("update person set name=?,age=? where id=?");
prst.setString(1,person.getName());
prst.setInt(2,person.getAge());
prst.setInt(3,person.getId());
return prst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(prst,conn);
}
return 0;
}
public int delete(int id) {
Connection conn = null;
PreparedStatement prst = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("delete from person where id=?");
prst.setInt(1,id);
return prst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(prst,conn);
}
return 0;
}
public Person selectById(int id) {
Connection conn = null;
PreparedStatement prst = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("select * from person where id=?");
prst.setInt(1,id);
rs = prst.executeQuery();
if(rs.next()){
String name = rs.getString("name");
int age = rs.getInt("age");
Date bornDate = rs.getDate("bornDate");
String email = rs.getString("email");
String address = rs.getString("address");
return new Person(id,name,age,bornDate,email,address);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(rs,prst,conn);
}
return null;
}
public List<Person> selectAll() {
Connection conn = null;
PreparedStatement prst = null;
ResultSet rs = null;
List<Person> list = new ArrayList<>();
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("select * from person");
rs = prst.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
Date bornDate = rs.getDate("bornDate");
String email = rs.getString("email");
String address = rs.getString("address");
list.add(new Person(id,name,age,bornDate,email,address));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(rs,prst,conn);
}
return list;
}
}
3.1 DateUtils
日期工具类
在项目中,针对日期类可能需要相互转化
例如:String转Date,Date转String,Utils的Date转SQL的Date
//日期类的转换方法:
public class DateUtils {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static Date utilToSQL(java.util.Date date){
return new Date(date.getTime());
}
public static String utilToString(java.util.Date date){
return sdf.format(date);
}
public static java.util.Date stringToUtil(String strDate){
try {
return sdf.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
4.Service业务层(重点)
用于进行业务逻辑分析,一个业务功能可以包含一个或多个dao操作
例如:转账业务–>细化分析
一个业务–>多个dao,判断发送方账户,接收方账户正确性,钱是否足够
最后才能做转账功能–一个账户加钱,另一个用户减钱
以上都是业务分析范畴

案例:转账业务功能分解
- 创建一张表account,有以下列:
- id:int,主键,自动增长
- cart :varchar(40) 非空
- password : 字符串
- money :double(8,2)
//操作步骤:
//1.创建数据表,插入两条数据
//2.创建实体类Account
//3.创建DBUtils数据库工具类
//4.创建业务层,进行转账业务分析
//5.具体与数据库交互,交给dao层
//6.在测试类中进行测试
//---------创建实体类---------
//创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private int id;
private String card;
private String password;
private double money;
}
//----------业务逻辑分析-----------
//转账业务类
public class AccountServiceImpl {
private AccountDaoImpl accountDao = new AccountDaoImpl();
//转账的业务功能
public String tansfer(String sendCard,double money,String recvCard,String password){
//1.根据发送方账户,获取对象,如果没有则报异常
Account sendAccount = accountDao.selectCard(sendCard);
if(sendAccount==null){
throw new RuntimeException("发送方账户不存在!");
}
//2.如果有,拿到了对象,看看密码是否正确,金额够不够
if(!password.equals(sendAccount.getPassword())){
throw new RuntimeException("密码错误");
}
if(sendAccount.getMoney()<money){
throw new RuntimeException("余额不足");
}
//3.判断接收方账户是否存在,如果不存在,则报异常
Account recvAccount = accountDao.selectCard(recvCard);
if(recvAccount==null){
throw new RuntimeException("接收方账户不存在");
}
//4.进行转账-->发送方减钱(update),接收方加钱(update)
sendAccount.setMoney(sendAccount.getMoney()-money);
int result = accountDao.update(sendAccount);
System.out.println("发送方修改:"+result);
recvAccount.setMoney(recvAccount.getMoney()+money);
result = accountDao.update(recvAccount);
System.out.println("发送方修改:"+result);
return "转账成功~~!";
}
}
//----------数据访问层----------
public class AccountDaoImpl {
public Account selectCard(String card) {
Connection conn = null;
PreparedStatement prst = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("select * from account where card=?");
prst.setString(1,card);
rs = prst.executeQuery();
if(rs.next()){
int id = rs.getInt("id");
String password = rs.getString("password");
double money = rs.getDouble("money");
return new Account(id,card,password,money);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(rs,prst,conn);
}
return null;
}
public int update(Account recvAccount) {
Connection conn = null;
PreparedStatement prst = null;
try {
conn = DBUtils.getConnection();
prst = conn.prepareStatement("update account set money=? where id=?");
prst.setDouble(1,recvAccount.getMoney());
prst.setInt(2,recvAccount.getId());
return prst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.closeAll(prst,conn);
}
return 0;
}
}
//-------------测试类-------------
public class Test1 {
public static void main(String[] args) {
AccountServiceImpl accountService = new AccountServiceImpl();
String res = accountService.tansfer("10010",1000,"10086","123");
System.out.println(res);
}
}
边栏推荐
猜你喜欢

应用挂了~

图片降噪DeNoise AI

APP自动化测试-Appium进阶

Sift特征点提取

Visual display of TEQC quality analysis results using teqcplot

AMS:startActivity桌面启动应用

架构师之路,从「存储选型」起步

Arduino temperature and humidity sensor DHT11 (including code)

985 test engineer is hanged. Who is more important in terms of education and experience?

MVC three-tier architecture
随机推荐
Cookie session explanation
同步国内AOSP代码相关错误
Swiftui 2.0 course notes Chapter 5
(IntelliJ) plug in background image plus
【Laravel系列7.8】广播系统
UI自动化定位利器-xpath实战
飞桨框架v2.3发布高可复用算子库PHI!重构开发范式,降本增效
Complete the primary school project in 3 days, and teach you to complete the weather broadcast system hand in hand!
Event log keyword: eventlogtags logtags
Missing essential plugin
How can functional testers spend one month to become advanced automation software test engineers
bat中获取bat命令结果
The tiobe programming language ranking is an indicator of the popular trend of programming languages
如何进行探索性数据分析
【opencv450】帧间差分法
618 how to break through the siege? Haier Zhijia: do a good job in digitalization of users
C'est dur de trouver un emploi? Ali des trois côtés, heureusement qu'il s'est bien préparé et qu'il a pris un produit.
JDBC call stored procedure, MySQL trigger
投资风险管理
导出带水印的PDF