连接数据库(JDBC)后,增删改查(CRUD)的封装升级(ORM)

说明:此篇博文是在初级封装的基础上进行的,可先看:

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待续

Hibernate的学习:

https://blog.csdn.net/Carl_changxin/article/details/82118089

猜你喜欢

转载自blog.csdn.net/Carl_changxin/article/details/82114202
今日推荐