JAVA & 数据库编程 & ORM工具(下)

本文前置内容:JAVA & 数据库编程 & ORM工具(上)

一、ORM的数据库操作

1.链接数据库准备

public class YORM {
	private static Connection connection;
	public YORM() {
	}
	
	public static void initORM(String cfgPath) {
		try {
			PropertiesParse.loadProperties(cfgPath);
			//利用Properties文件配制
			Class.forName(PropertiesParse.getValue("driver"));
			connection = DriverManager.getConnection(
					PropertiesParse.getValue("url"),
					PropertiesParse.getValue("user"),
					PropertiesParse.getValue("password"));
		} catch (PropertiesFileNotFoundException | IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

文件如图
在这里插入图片描述注意url的书写,其中school是我用的数据库名。

关键操作

其实无论是增删改查,都是按照一定的步骤来的。

  1. 第一步,获取映射关系类
  2. 第二步,构建基本的sql语句结构
  3. 第三步,通过模板类,完善sql语句
  4. 第四步,执行操作,处理返回结果

这里面的一个需要注意的地方:由于模板类的成员是private保护,无法直接对其进行操作。
而使用field.setAccessible(true);会破坏其保护。但有趣的是,我们拥有set,get函数。而且其一般规则是
set方法 : set + 成员名(首字母大写)(成员类型){}
get方法:get + 成员名(首字母大写)(){}
所以我们可以通过**使用反射获取方法,来实现对成员的读写。

具体get


	private Object getFieldValue(Class<?> kClass, Field field, Object object) {
		String fieldName = field.getName();
		//注意,由于成员是private保护,不能直接获取,但是可通过get函数获得
		String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
		try {
			Method method = kClass.getDeclaredMethod(methodName);
			Object value = method.invoke(object, new Object[] {});
			return value;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

具体set

	private void initObject(ClassTableDefinition ctd, Object result, ResultSet resultSet) {
		Class<?> modelKClass = result.getClass();
		List<FieldCloumnDefinition> fdList = ctd.getfDefinitions();
		
		for (FieldCloumnDefinition fd : fdList) {
			try {
				Object value = resultSet.getObject(fd.getCloumn());
				System.out.println(value.getClass());
				Field field = fd.getField();
				String fieldName = field.getName();
				//set
				String methodName = "set" + fieldName.substring(0, 1).toUpperCase() 
						+ fieldName.substring(1);
				Method method = modelKClass.getDeclaredMethod(methodName, field.getType());
				method.invoke(result, value);
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

2、增

熟悉增加操作:INSERT INTO 表名([字段名1,字段名2,字段名3])VALUES(‘值1’,‘值2’,‘值3’),(‘1值1’,‘1值2’,‘1值3’)…

	/**
	 * 从一个类中将一条完整的记录存储到数据库中。
	 * @param object
	 */
	public void save(Object object) {
		//第一步,获取映射关系类
		Class<?> kClass = object.getClass();
		ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass);
		
		if (ctd == null) {
			System.out.println("类[" + kClass.getName() + "]没有映射关系!");
		}
		StringBuffer sql = new StringBuffer();
		//第二步,构建基本的sql语句结构
		sql.append("INSERT INTO ").append(ctd.getTableName())
			.append(" (").append(ctd.getCloumnList())
			.append(") VALUES(");
		for (int index = 0; index < ctd.getFieldCount(); index++) {
			sql.append(index == 0 ? "" : ",").append("?");
		}
		sql.append(");");
		PreparedStatement statement;
		try {
			statement = connection.prepareStatement(sql.toString());
			//第三步,通过模板类,完善sql语句
			//INSERT INTO student (student.id,student.name,student.age) VALUES(?,?,?);  上面获得sql语句
			//接下来需要将?,一一修改成存储在模板类的数据
			prepareStatment(ctd, statement, object);
			//第四步,执行操作
			statement.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	private void prepareStatment(ClassTableDefinition ctd, PreparedStatement statement, Object object) {
		Class<?> kClass = object.getClass();
		List<FieldCloumnDefinition> fdList = ctd.getfDefinitions();
		int index = 0;
		for (FieldCloumnDefinition fd : fdList) {
			Field field = fd.getField();
			//获取到每个成员的值,完成sql语言
			Object value = getFieldValue(kClass, field, object);
			try {
				System.out.println(value);
				statement.setObject(index + 1, value);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			index++;
		}
	}

3、删

熟悉删除操作:语法: DELETE FROM 表名 [WHERE 条件]

	/**
	 * 通过主键值,删除某一条记录
	 * @param kClass
	 * @param id
	 */
	public void delete(Class<?> kClass,Object id) {
		ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass);
		if (ctd == null) {
			System.out.println("类[" + kClass.getName() + "]没有映射关系!");
			return;
		}
		StringBuffer sql = new StringBuffer();
		
		sql.append("DELETE ").append("FROM ").append(ctd.getTableName())
		.append(" WHERE ").append(ctd.getPrimaryKey().getCloumn())
		.append("=?;");

		//DELETE FROM student WHERE id=?;
		try {
			PreparedStatement statement = connection.prepareStatement(sql.toString());
			statement.setObject(1, id);
			
			statement.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

4、改

熟悉修改操作:UPDATE 表名 SET colnum_name = value,[colnum_name = value, …] where [条件]

	/**
	 * 修改一个记录
	 * @param object
	 */
	public void update(Object object) {
		Class<?> kClass = object.getClass();
		ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass);
		//第一步
		if (ctd == null) {
			System.out.println("类[" + kClass.getName() + "]没有映射关系!");
		}
		
		StringBuffer sql = new StringBuffer();
		sql.append("UPDATE ").append(ctd.getTableName())
		.append(" SET");
		
		List<FieldCloumnDefinition> fList = ctd.getfDefinitions();
		boolean isFirst = true;
		for (FieldCloumnDefinition fcd : fList) {
			if (fcd.equals(ctd.getPrimaryKey())) {
				continue;
			}
			String cloumnName = fcd.getCloumn();
			sql.append(isFirst ? " ": ",").append(cloumnName)
			.append("=?");
			isFirst = false;
		}
		sql.append(" WHERE ").append(ctd.getPrimaryKey().getCloumn()).append("=?;");
		//第二步完成
		//UPDATE student SET name=?,age=? WHERE id=?;
		try {
			PreparedStatement statement = connection.prepareStatement(sql.toString());
			int index = 0;
			for (FieldCloumnDefinition fd : fList) {
				if (fd.equals(ctd.getPrimaryKey())) {
					continue;
				}
				//第三步关键
				Object value = getFieldValue(kClass, fd.getField(), object);
				statement.setObject(++index, value);
				
			}
			Object idValue = getFieldValue(kClass, ctd.getPrimaryKey().getField(), object);//get
			statement.setObject(++index, idValue);
			//第四步执行
			statement.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

5、查

查目前提供两种,查一条匹配记录,和查表中所有记录。
查一条:SELECT 字段名, 字段名… FROM 表名 WHERE[条件]

	/**
	 * 根据某一条件,查询一条完整的记录
	 * @param <T>
	 * @param kClass SELECT查询结果生成的对象
	 * @param id  WHERE 使用的主键条件
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T>T get(Class<?> kClass, Object id){
		//第一步
		ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass);
		if (ctd == null) {
			System.out.println("类[" + kClass.getName() + "]没有映射关系!");
			return null;
		}
		//生成查询语句,第二步
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT ").append(ctd.getCloumnList())
			.append(" FROM ").append(ctd.getTableName())
			.append(" WHERE ").append(ctd.getPrimaryKey().getCloumn()).append("=?;");
		
		//SELECT student.id,student.name,student.age FROM student WHERE id=?;
		Object result = null;

		try {
			PreparedStatement statement = connection.prepareStatement(sql.toString());
			statement.setObject(1, id);//第三步简单

			ResultSet resultSet = statement.executeQuery();
			if (resultSet.next()) {
				result = newInstance(ctd, resultSet);//将数据保存到模板类中
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return (T) result; 
	}

	private Object newInstance(ClassTableDefinition ctd, ResultSet resultSet) 
			throws InstantiationException, IllegalAccessException {
		Class<?> kClass = ctd.getModelClass();
		Object result = kClass.newInstance();
		initObject(ctd, result, resultSet);//set
		return result;
	}

查询所有记录SELECT * FROM student

	/**
	 * 获得表中所有数据
	 * @param <T>
	 * @param kClass
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> list(Class<?> kClass){
		ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass);
		
		if (ctd == null) {
			System.out.println("类[" + kClass.getName() + "]没有映射关系!");
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT ").append("* ")
			.append("FROM ").append(ctd.getTableName());
		//SELECT * FROM student
		List<T> result = new ArrayList<T>();
		
		try {
			PreparedStatement statement = connection.prepareStatement(sql.toString());
			ResultSet rs = statement.executeQuery();			
			while (rs.next()) {
				T element = (T) newInstance(ctd, rs);
				result.add(element);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

二、小总结

其实虽然完成了增删改查,但还是又不少地方有待完善。比如说排序,比如查询指定记录的少数列数据。

因为上述操作都是针对一条完整记录。不过从整体而言,只要规范好sql语句的搭建,就能实现基本功能。所以称之为工具不为过。当然,工具也是越用越好用。(不断完善)


笔者水平有限,目前只能描述以上问题,如果有其他情况,可以留言,有错误,请指教,有继续优化的,请分享,谢谢!
本篇文章是否有所收获?阅读是否舒服?又什么改进建议?希望可以给我留言或私信,您的的分享,就是我的进步。谢谢。


2020.10.24 网安院2楼

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值