说明:此篇博文是在初级封装的基础上进行的,可先看:https://blog.csdn.net/Carl_changxin/article/details/82112563
1、回顾并说明在何处优化
(1)上篇博文在保存数据时,有两个多余的操作,实例化JDBC对象,自定义sql语句
(2)ORM对象关系模型, 表示实体类对应数据库中的一张表,一个实体对象对应表中的一条数据
即设定好对象的属性和表的列名是一致的
(3)因为通过反射可以获取对象属性,当我们设定好对象的属性和表的列名是一致的,那么执行sql
就不需要传参,并且sql语句可以自动拼接,不用再自己写
(4)创建一个BaseDao类,在封装的基础上再封装:
说明这个类的内容:
1、实例化JDBC对象
2、获取当前实体对象的class属性(进行反射),获取要操作的表的名称(sql需要)
3、自动拼接sql语句,如save方法对应JDBC类中的insert方法,在save中先拼接好相应
的sql语句,再调用insert方法,sql语句作为insert方法的参数
package util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import entity.Blog;
/**
*1、实体类去继承该类,该类会提供增删改查的方法,让实体对象去调用
*2、 实体类对应数据库中的一张表,一个实体对象对应表中的一条数据
*3、该类中提供的增删改查方法,只是拼接了sql语句,再交给JDBC去做
*4、sql语句的可变部分可以看做是对象的属性和属性值,因此可以通过反射去获取实体对象的属性和属性值,拼接sql语句
* @param <T>
*/
public class BaseDao<T> {
private JDBC jdbc = JDBC.getInstance();
//获取要操作的对象的class属性
private Class cls = this.getClass();
//要传入要操作的表的名称
private String tableName;
public BaseDao(String tableName){
this.tableName = tableName;
}
/**
* 保存对象到数据库
* insert into 表名(列名/属性名...) value (属性值);
* @return 影响的行数
*/
public int save(){
/**拼接插入语句*/
StringBuffer insertSql = new StringBuffer("insert into "+tableName+" (");
StringBuffer fieldsSql = new StringBuffer();
StringBuffer fieldsValSql = new StringBuffer();
Field[] fields = cls.getDeclaredFields();
try {
for(Field f : fields){
f.setAccessible(true);
//当属性名不是id并且属性值不为空时,把该属性当作插入条件之一
if(!"id".equals(f.getName()) && f.get(this) != null ){
fieldsSql.append("`"+f.getName()+"`"+",");
fieldsValSql.append("'"+f.get(this)+"'"+",");
}
}
} catch (Exception e) {
e.printStackTrace();
}
if(fieldsSql.length()!=0) {
fieldsSql.replace(fieldsSql.length()-1, fieldsSql.length(), "");
fieldsValSql.replace(fieldsValSql.length()-1, fieldsValSql.length(), "");
}
insertSql.append(fieldsSql+") value ("+fieldsValSql+");");
System.out.println(insertSql);
return jdbc.insert(insertSql.toString());
}
/**
* 根据当前对象的属性进行删除,以不为空的属性作为删除的过滤添加
* delete from tableName where 属性1名=属性1值 and 属性2名=属性2值 ...
* @return 影响的行数
*/
public int remove(){
StringBuffer deleteSql = new StringBuffer();
StringBuffer attrVal = new StringBuffer();
/**获得类中所有的属性*/
Field[] fields = cls.getDeclaredFields();
for(Field f : fields){
f.setAccessible(true);
try {
if(f.get(this) != null){
attrVal.append("`"+f.getName()+"`='"+f.get(this)+"' and ");
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
attrVal.replace(attrVal.length()-4, attrVal.length(), "");
deleteSql.append("delete from `"+tableName+"` where "+attrVal+";");
System.out.println(deleteSql);
return jdbc.delete(deleteSql.toString());
}
/**
* 修改对象对应数据库中的列
* //update t_user set name='',age='' where id=''
* @return 影响的行数
*/
public int alertById(){
StringBuffer updateSql = new StringBuffer();
StringBuffer attrVal = new StringBuffer();
Integer idVal = null;
/**获得类中所有的属性*/
Field[] fields = cls.getDeclaredFields();
for(Field f : fields){
f.setAccessible(true);
try {
if(!"id".equals(f.getName())){
if(f.get(this) != null){
attrVal.append("`"+f.getName()+"`='"+f.get(this)+"',");
}
}else{
if(f.get(this) == null){
System.out.println("id没有值");
}else{
idVal = (Integer) f.get(this);
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
attrVal.replace(attrVal.length()-1, attrVal.length(), "");
updateSql.append("update `"+tableName+"` set "+attrVal+" where "+"`id`='"+idVal+"';");
System.out.println(updateSql);
return jdbc.update(updateSql.toString());
}
/**
* 查找符合条件的数据
* select * from tableName where ...
* @return 查找到的结果,转化成对象
*/
public List<T> find(){
StringBuffer querySql = new StringBuffer("select * from "+tableName);
StringBuffer attrVal = new StringBuffer();
Field[] fields = cls.getDeclaredFields();
for(Field f : fields){
f.setAccessible(true);
try {
if(f.get(this) !=null){
attrVal.append("`"+f.getName()+"`='"+f.get(this)+"' and ");
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
if(attrVal.length() != 0){
attrVal.replace(attrVal.length()-4, attrVal.length(), "");
querySql.append(" where "+attrVal+";");
}else{
querySql.append(";");
}
System.out.println(querySql);
//查询出来的结果开始是结果集,然后转化成List<Map<String,Object>>集合,再转化成对象
List<Map<String,Object>> lists = jdbc.query(querySql.toString());
//遍历lists集合
try {
List<T> list = new ArrayList<T>();//用来存放对象
for(Map<String,Object> m : lists){
@SuppressWarnings("unchecked")
T t = (T)cls.newInstance();
//遍历Map集合,一个Map集合对应一个对象
for( Map.Entry<String,Object> entry: m.entrySet() ){
//根据列名称,获取当前对象的对应该列的属性
Field f = cls.getDeclaredField(entry.getKey());
//设置对象的属性值
f.setAccessible(true);
f.set(t, entry.getValue());
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
2、使用
(1)Blog类要继承BaseDao类,才能直接调用其中的方法;注意Date改成了String类型,保存的时候就不需要转化了
package entity;
import java.util.Date;
import util.BaseDao;
public class Blog extends BaseDao<Blog>{
public Blog() {
super("t_blog");
}
private Integer id;
private String title;
private String content;
private String type;
private String date;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
(2)创建Run2类,Run2.java:
package run;
import java.text.SimpleDateFormat;
import java.util.Date;
import entity.Blog;
public class Run2 {
public static void main(String[] args) {
/*实例化Blog对象*/
Blog blog = new Blog();
/*初始化blog对象*/
blog.setTitle("JAVA学习之JDBC");
blog.setContent("一点都不难");
blog.setType("编程语言");
//当前系统Date,按照指定格式(datatime格式)转化成字符串,保存到数据库,就不要转化了
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
String dateTime = df.format(date);
blog.setDate(dateTime);
blog.save();
}
}
(3)结果
3、好处
感觉上像是直接操作对象,不需要考虑到底是怎么存储到数据库的
4、Hibernate的底层思想就是在JDBC,CRUD封装的基础上,进一步封装
Hibernate的学习:https://blog.csdn.net/Carl_changxin/article/details/82118089