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

1、从普通数据库连接到ORM的遐想

如何通过jdbc让java语言和数据“联通”起来,想必是不难的。

		try {
			//1
			Class.forName("com.mysql.jdbc.Driver");
			
			Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school?"
					+ "useSSL=false", "root", "个人密码(例如123123)");
			//2
			String sqlStr = "SELECT id, name, age FROM student";
			
			PreparedStatement statement = connection.prepareStatement(sqlStr);
			ResultSet rSet = statement.executeQuery();
			//3
			while(rSet.next()) {
				String stuID = rSet.getString("id");
				String stuName = rSet.getString("name");
				String stuAge = rSet.getString("age");
				System.out.println(stuID +" "+ stuName +" " + stuAge);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

不难看出,以上程序有三大步骤。

  1. 链接数据库
  2. 构造并执行失去了语句
  3. 处理从数据库中得到的结果

对于每次对数据库的获取而言,步骤二和三是不可缺少的,但是对于链接数据库这一操作,是可以不用每使用一次就必须重新建立连接的。

当然,如果只是发现这一点,是不会想到ORM的。那么仔细研究数据表的模式和我们对数据库表的操作。

1、数据库是由:表、记录组成;
	SELECT查找的是由多条记录组成的“表”;
	INSERT INTO 插入的是一条相对完整的记录;
	UPDATE 是对一条,或多条复合要求的记录进行修改;
	DELETE 删除的是复合条件的记录……
2、Java的面向对象编程思想:
	类;
	对象。
将上述两种不同的操作,按照数据对等性,可以这样看:
表 <=> 类
	表是由多个字段描述而成的;
	类是由多个成员描述而成的;
记录 <=> 对象
	记录是那些字段的某一次取值的集合;
	对象是那些成员的某一次取值的集合。

在研究我们对于数据的增删改查

这些操作的统一SQL语句可以描述为:
查找指定的一条记录:
	SELECT 字段表 
		FROM 表名称 
		WHERE 关键字段=value;
查找所有记录:
	SELECT 字段表 
		FROM 表名称;
插入一条记录:
	INSERT INTO 表名称
		(字段表)
		VALUES (字段值表);
		……
上述SQL语句的创建,可不可以“自动化”?如果能自动化,那么,这些
SQL语句的执行更容易自动化……
上述想法能得以实现的关键不确定点是:
	字段表;
	字段名称;
	字段的值;
	从结果集中取得的记录存储方式……
如果上述问题能够得以解决,那么,有关数据库表访问,完全可以
自动化.

最终引出我们的ORM:Object Relation Mapping
Object就是Java的对象;
Relation就是关系型数据库;
Mapping就是“映射关系”。
同时,让我们看看最后完成工具的时候,使用数据库如何轻松。
在这里插入图片描述其中实现的PreparedStatement,一定程度上防止了sql注入

2、配置文件

第一个配置文件,是从个人连接数据库的必要数据中提取出来的。
在这里插入图片描述固定的驱动类名,固定的个人数据库位置(自定义),用户名(使用者自行配置),密码(使用者自行配置)。

在这里插入图片描述property文件。
第二个配置文件,也是实现ORM的基础。就是表与类之间的关系映射。
举个例子:
在这里插入图片描述
上述是一张学生信息的表(虽然数据很少)。表名是 student ,位于school数据库下。表有三个属性,分别是id, name, age。其中id为主键。
那么用一个类来如何描述呢?
在这里插入图片描述
我们建立一个模板类。就叫做学生信息。

public class StudentInfo {
	private String stuId;
	private String stuName;
	private String stuAge;
	
	public StudentInfo() {
	}

	public String getStuId() {
		return stuId;
	}

	public void setStuId(String stuId) {
		this.stuId = stuId;
	}
	//省略些,get,set方法

	@Override
	public String toString() {
		return "StudentInfo [stuId=" + stuId + ", stuName=" + stuName + ", stuAge=" + stuAge + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((stuId == null) ? 0 : stuId.hashCode());
		return result;
	}
	//stuId作为两个实例是否不同的筛选因子。对于表中的主键。
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		StudentInfo other = (StudentInfo) obj;
		if (stuId == null) {
			if (other.stuId != null)
				return false;
		} else if (!stuId.equals(other.stuId))
			return false;
		return true;
	}
}

看完表,再看完类,是否找到了映射关系?xml文件配置自然来。

<?xml version="1.0" encoding="UTF-8"?>
<mappings>
	<mapping class = "com.mec.about_orm.model.StudentInfo" table = "student">//类和表一对一
		<field name = "stuId" cloumn = "id"></field>//cloumn 列,属性,对应着类的成员名
		<field name = "stuName" cloumn = "name"></field>
		<field name = "stuAge" cloumn = "age"></field>
		<key name = "id"></key>
	</mapping>
</mappings>

3、完成类与表的映射关系

此时我们在仔细看看我们拥有什么

  • 一张xml文件
  • 一个java存储数据的模板类
  • 一个数据库中一张完整的表
    那么关键,自然是在xml文件上。
    我们需要做的工作就是,扫描xml文件形成,将一个表的映射类给完整描述出来。
    先看类成员与表的属性对应
    在这里插入图片描述
    定义一个类 FieldCloumnDefinition:
public class FieldCloumnDefinition {
	private Field field;//成员
	private String cloumn;
	
	public FieldCloumnDefinition() {
	}
	//成员的get, set方法略
	@Override
	public String toString() {
		return field.getName() +"<=>" + cloumn;
	}
}

接着再看类与表的映射
在这里插入图片描述
定义一个表和类映射关系的类:
在这里插入图片描述元数据,实例都是为反射使用做准备。
接下来,开始扫描xml文件。(如果不清楚我扫描xml文件的方式,可以看这篇文章JAVA & 自建工具类 & xml文件解析工具

第一步:扫描表和类的映射关系
在这里插入图片描述扫描成功后获得表名,与类的具体地址。这时可以将类地址作为键值,将映射关系类作为值。形成映射池。其中给模板类的元数据复制的是setkClass方法,如下:

	void setkClass(String className) {
		try {
			this.modelClass = Class.forName(className);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

给表名赋值就不说了。至此,映射关系类,成员已有二,差三。
第二步:扫描内部的成员和列映射
这里其实有两个标签扫描

				new XMLParse() {
					
					@Override
					public boolean dealElement(Element element, int index) {
						String fieldName = element.getAttribute("name");
						String cloumnName = element.getAttribute("cloumn");
						ctd.setTrueCloumnName(fieldName, cloumnName);
						return true;
					}
				}.parseElement(element, "field");

第一个是对“field”标签扫描。

	void setTrueCloumnName(String fieldName, String cloumnName) {

		Field[] fields = this.modelClass.getDeclaredFields();//利用反射获得所有成员
		if (fields.length <= 0) {
			return;
		}
		for (Field field : fields) {
			if (fieldName.equals(field.getName())) {//匹配成员名,将映射的成员与列类完成
				FieldCloumnDefinition fcd = new FieldCloumnDefinition();
				fcd.setCloumn(cloumnName);
				fcd.setField(field);
				this.fDefinitions.add(fcd);
			}
		}
	}

至此,又多了个成员完成,且获得了完整的FieldCloumnDefinition类。

	new XMLParse() {
					
					@Override
					public boolean dealElement(Element element, int index) {
						String keyName = element.getAttribute("name");
						
						ctd.setKeyCloumn(keyName);
						return false;
					}
				}.parseElement(element, "key");

第二个是对“key”扫描

	void setKeyCloumn(String keyName) {
		if (this.fDefinitions.size() == 0) {
			return;
		}
		for (FieldCloumnDefinition fd : this.fDefinitions) {
			if(keyName.equals(fd.getCloumn())) {//主键名和已形成的成员列映射类的列名相同
				this.primaryKey = fd;
			}
		}
	}

到此,除了object成员,其他成员都已经有了。而object只有get,set方法。
那么,前三个类都已经完成了。分别是类与表的映射,成员与列名映射,扫描xml文件形成映射池
在这里插入图片描述
只剩下最后的ORM类。

点击链接,继续ORM构造吧。

代码资源会放在下一篇中。JAVA & 数据库编程 & ORM工具(下)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值