自定义框架(一)—— ORM 框架

一、ORM 框架

1、ORM 框架概念

(1)O(对象):表示程序中的对象
(2)R(关系):表示关系型数据库
(3)M(模型):将java中的对象和关系型数据中的数据进行一一映射(类与表进行映射,属性与字段进行映射),在此模型的基础上可以用面向对象的方式操作数据库

2、自定义框架案例

(1)配置 jdbc.xml 文件,里面包括 driver、url、user、password。

<?xml version="1.0" encoding="UTF-8"?>
<jdbc>
    <property name="driver">com.mysql.jdbc.Driver</property>
    <property name="url">jdbc:mysql://localhost:3306/woniushop?useUnicode=true&amp;characterEncoding=utf-8</property>
    <property name="user">root</property>
    <property name="password">admin</property>
</jdbc>

(2)JDBCInfo 实体类对象,用于

public class JDBCInfo {
	private String driver;
	private String url;
	private String user;
	private String password;
	
	//定义字符串类型的集合 保存所有需要扫描的实体类名称
	private List<String> classNames;
	
	public List<String> getClassNames() {
		return classNames;
	}
	public void setClassNames(List<String> classNames) {
		this.classNames = classNames;
	}
	public String getDriver() {
		return driver;
	}
	public void setDriver(String driver) {
		this.driver = driver;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

(3)解析 jdbc.xml 配置文件

public class JDBCXMLReader {
	//定义读取jdbc.xml的方法 将读取出的信息封装到JDBCInfo对象中
	public static JDBCInfo readJDBC() {
		JDBCInfo jdbc = new JDBCInfo();
		
		//使用dom4j解析方式解析jdbc.xml文件
		//创建dom4j读取xml的对象
		SAXReader reader = new SAXReader();
		try {
			//读取文件形成文档对象
			Document document = reader.read("src/jdbc.xml");
			//从文档对象中取出根标签
			Element rootElement = document.getRootElement();
			//取出根标签的property子标签,得到一个子标签集合
			List<Element> propertyElements = rootElement.elements("property");
			//循环遍历集合得到标签中driver、url、user、password的值
			for(Element e: propertyElements) {
				//attributeValue获取标签属性值
				if(e.attributeValue("name").equals("driver")) {
					//getText获取标签文本
					jdbc.setDriver(e.getText());
				}
				if(e.attributeValue("name").equals("url")) {
					//getText获取标签文本
					jdbc.setUrl(e.getText());
				}
				if(e.attributeValue("name").equals("user")) {
					//getText获取标签文本
					jdbc.setUser(e.getText());
				}
				if(e.attributeValue("name").equals("password")) {
					//getText获取标签文本
					jdbc.setPassword(e.getText());
				}
			}
			
			//读取根标签中的mapping标签中的class标签
			List<Element> classElements = rootElement.element("mapping").elements("class");
			List<String> list = new ArrayList<String>();
			
			//遍历classElements并将所有的值存入到集合中
			for(Element e: classElements) {
				list.add(e.attributeValue("name"));
			}
			jdbc.setClassNames(list);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jdbc;
	}
}

(4)建立自定义注解
① 表注解:用于保存表名

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableAnnotation {
	//设置属性用来保存所有的表名
	String value();
}

@interface表示该注解可以被继承

② 列注解:用于保存列名

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnAnnotion {
	//设置属性值用来保存所有的列名
	String value();
}

(5)创建 ClassInfo 类对象和 PropertyInfo类
① ClassInfo:用于保存每个类所有的表名

public class ClassInfo {
	private String name;
	private String table;
	private List<PropertyInfo> properties=new ArrayList<PropertyInfo>();
	
	public List<PropertyInfo> getProperties() {
		return properties;
	}
	public void setProperties(List<PropertyInfo> properties) {
		this.properties = properties;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getTable() {
		return table;
	}
	public void setTable(String table) {
		this.table = table;
	}
}

② PropertyInfo :用于每个表的所有列的属性和值

public class PropertyInfo {
	private String name;
	private String column;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getColumn() {
		return column;
	}
	public void setColumn(String column) {
		this.column = column;
	}
}

(6)QueryOperate 类:用于定义方法,如常用的增删改查,这里定义一个查询示例

public class QueryOperate {
	public static final Map<String, ClassInfo> map = new HashMap<String, ClassInfo>();
	private static JDBCInfo info;
	
	//加载该类时 需要读取jdbc.xml信息
	static {
		//调用读取xml文件的方法 获取JDBCInfo对象
		info = JDBCXMLReader.readJDBC();
		try {
			//创建连接
			Class.forName(info.getDriver());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//非空判断
		if(info.getClassNames() != null) {
			//扫描实体类 获取实体类映射信息 
			for(String className: info.getClassNames()) {
				//每一个实体类扫描的结果都应该对应一个ClassInfo对象
				ClassInfo classInfo = new ClassInfo();
				
				//获取类的字节码信息
				try {
					Class c = Class.forName(className);
					//扫描实体类上的table注解
					TableAnnotation table = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
					//获取table注解的值
					String tableName = table.value();
					//将table注解的值 也就是表名存到classinfo对象中
					classInfo.setTable(tableName);
					
					//获取该类上自己定义的所有属性
					Field[] fields = c.getDeclaredFields();
					//循环所有的属性 获取属性名和列名
					if(fields != null) {
						for(Field field: fields) {
							//每一个属性对应一个PropertyInfo对象
							PropertyInfo propertyInfo = new PropertyInfo();
							propertyInfo.setName(field.getName());
							propertyInfo.setColumn(field.getName());
							if(field.isAnnotationPresent(ColumnAnnotation.class)) {
								//如果有该注解说明这个属性的列名是跟属性名称不一致
								//取出注解中的值
								ColumnAnnotation column = field.getAnnotation(ColumnAnnotation.class);
								propertyInfo.setColumn(column.value());
							}
							//将该对象保存到classinfo的集合中
							classInfo.getProperties().add(propertyInfo);
						}
					}
					//将classinfo保存到一个全局的键值对中
					//用类的全限定名作为键 该类的映射信息作为值保存到键值对中
					map.put(className, classInfo);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	public List select(Class c) throws Exception{
		//通过class信息得到类名
		String className = c.getName();
		//通过类名得到该类的映射信息ClassInfo对象
		ClassInfo classInfo = map.get(className);
		//获取连接
		Connection conn = DriverManager.getConnection(info.getUrl(), info.getUser(), info.getPassword());
		PreparedStatement ps = conn.prepareStatement("select * from " + classInfo.getTable());
		ResultSet result = ps.executeQuery();
		List list = new ArrayList();
		while(result.next()) {
			Object entity = c.newInstance();
//			System.out.println(entity);
			//循环classinfo中的属性映射集合
			for(PropertyInfo pi: classInfo.getProperties()) {
				//从查询到的结果集中取出每一列的值
				Object propertyValue = result.getObject(pi.getColumn());
				System.out.println(propertyValue);
				//取出该属性对象
				Field field = c.getDeclaredField(pi.getName());
				//获取该属性的set方法
				//通过属性名取出第一个字母转大写+第二到最后的所有字母 就是属性名首字母大写
				String methodName = "set" + pi.getName().substring(0, 1).toUpperCase() + pi.getName().substring(1);
				System.out.println(methodName);
				//获取set方法
				//属性对象.getType获取的是 该属性的类型
				Method method = c.getMethod(methodName, field.getType());
				System.out.println(field.getType());
				//通过调用set方法给该属性赋值
				method.invoke(entity, propertyValue);
			}
			list.add(entity);
		}
		result.close();
		ps.close();
		conn.close();
		return list;
	} 
}

(7)定义要查询的表对应的类,如

@TableAnnotation("products")
public class Products {
	private int p_id;
	private String p_name;
	private double p_price;
	private int p_count;
	private String p_class;
	private String p_attribute;
	private int p_typeid;
	
	public int getP_id() {
		return p_id;
	}
	public void setP_id(int p_id) {
		this.p_id = p_id;
	}
	public String getP_name() {
		return p_name;
	}
	public void setP_name(String p_name) {
		this.p_name = p_name;
	}
	public double getP_price() {
		return p_price;
	}
	public void setP_price(double p_price) {
		this.p_price = p_price;
	}
	public int getP_count() {
		return p_count;
	}
	public void setP_count(int p_count) {
		this.p_count = p_count;
	}
	public String getP_class() {
		return p_class;
	}
	public void setP_class(String p_class) {
		this.p_class = p_class;
	}
	public String getP_attribute() {
		return p_attribute;
	}
	public void setP_attribute(String p_attribute) {
		this.p_attribute = p_attribute;
	}
	public int getP_typeid() {
		return p_typeid;
	}
	public void setP_typeid(int p_typeid) {
		this.p_typeid = p_typeid;
	}
	@Override
	public String toString() {
		return "Products [p_id=" + p_id + ", p_name=" + p_name + ", p_price="
				+ p_price + ", p_count=" + p_count + ", p_class=" + p_class
				+ ", p_attribute=" + p_attribute + ", p_typeid=" + p_typeid
				+ "]";
	}
}

(8)框架搭建完成,在实际运用中,首先需要在 jdbc.xml 文件中添加要查询的表对应的类,如,这里查询商品表:

<!--在jdbc.xml中配置项目中需要使用到的实体类 扫描这些实体类的注解 生成映射信息-->
<mapping>
    <class name="definedorm.orm0604.own.model.Products"></class>
</mapping>

(9)main 函数类:

public class Test1 {
	public static void main(String[] args) {
		QueryOperate query=new QueryOperate();
		try {
			List<Products> list =query.select(Products.class);
			//便利集合
			for(Products p:list) {
				System.out.println(p);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
发布了104 篇原创文章 · 获赞 58 · 访问量 7519

猜你喜欢

转载自blog.csdn.net/baidu_27414099/article/details/104440517