一、什么是ORM?
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/Rmapping),是一种程序技术,随着面向对象的软件开发方法发展而产生的。用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去,或者把表中的一条记录自动封装成对象。
采用ORM优势在于,程序员采用面向对象的方法来访问数据库,简化了编码,提高了开发速度,ORM自动完成类和表,属性名和字段名的映射。
使用本ORM框架,在处理查询业务逻辑时,只要编写形如"from 类名"的SQL语句,就可以得到封装好的所查询所有结果的List集合,处理添加业务时,只要调用Add(obj)方法即可实现添加功能。其他的功能读者可自行添加。
二、整体思路
1、自定义ORM注解,包含@Table和@Column。
2、写一个类,解析注解信息,并存入Map对象
3、实现查询和添加功能
4、使用自定义的ORM框架,实现业务逻辑
5、测试
三、具体实现
1、整体架构
2、建表并插入数据的SQL
showdatabases;
create database czf;
use czf;
create table stu(id int primary key,namevarchar(40),age int);
insert into stuvalues(1,'czf',34),(2,'afeng',25);
select * from stu;
createtable teacher(tid int primary key,tname varchar(40),tage int);
insertinto teacher values(1,'czf',34),(2,'afeng',25);
insert into teacher(tid,tname,tage)values(3,'czf3',33);
select * from teacher;
3、具体代码
第一部分 ORM部分代码的编写
3.1 Table.java
packagecn.com.bochy.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解,用于注解类名所对应的表名
* @authorchenzhengfeng
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
String value();//表名
}
3.2 Column.java
package cn.com.bochy.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解,用于注解对象的属性名所对应的表的列名
* @authorchenzhengfeng
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String value();//列名
}
3.3 OrmImpl.java
package cn.com.bochy.orm;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import cn.com.bochy.annotation.Column;
import cn.com.bochy.annotation.Table;
/**
* 解析注解信息,并存入Map中
* @authorchenzhengfeng
*/
public class OrmImpl {
//用于存储类名对应的表名,其中key是类名,value是表名
private Map<String,String>mapTable=newHashMap<String,String>();
//用于属性名对应的表的字段名,其中key是属性名,value是字段名
private Map<String,String>mapColumns=newHashMap<String,String>();
public Map<String, String> getMapTable() {
returnmapTable;
}
public void setMapTable(Map<String, String> mapTable) {
this.mapTable =mapTable;
}
private StringtableName="";
public String getTableName() {
returntableName;
}
public void setTableName(String tableName) {
this.tableName =tableName;
}
public Map<String, String> getMapColumns() {
returnmapColumns;
}
public void setMapColumns(Map<String, String> mapColumns) {
this.mapColumns =mapColumns;
}
/**
* 解析实体类的注解信息,其中c1是实体类的类对象
* @param c1
*/
public void parseAnnotation(Class<?> c1) {
Table table=c1.getAnnotation(Table.class);
tableName=table.value();//获取注解的表名
mapTable.put(c1.getName(),tableName);//存入
Field[] fields=c1.getDeclaredFields();//获取所有的属性名
for(Fieldf:fields) {//遍历属性名
if(!f.getName().equals("serialVersionUID")) {
Column c=f.getAnnotation(Column.class);
mapColumns.put(f.getName(),c.value());//获取该属性名所对应的字段,并存入
}
}
}
}
3.4 OrmQuery.java
package cn.com.bochy.orm;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import cn.com.bochy.dbutil.DBHepler;
/**
* 实现查询功能
* @authorchenzhengfeng
*
*/
public class OrmQuery {
DBHepler helper=new DBHepler();
private static OrmImpl orm=null;
private static String tableName="";
private static Map<String,String> mapColumns=null;//存储属性和字段对应关系的MAP
private static Map<String,String> mapTables=null;//存储类名和表名对应关系的MAP
private Class<?>classc1;//查询对象的类对象
/**
* 通过构造方法实现初始化工作
* @param c1
*/
public OrmQuery(Class<?>c1) {
this.classc1=c1;
orm=new OrmImpl();
orm.parseAnnotation(classc1);//解析要查询对象的注解信息
tableName=orm.getTableName();
mapColumns=orm.getMapColumns();
mapTables=orm.getMapTable();
}
/**
* 查询sql形如"from类名"格式的语句,并封装成List,其他的形式请读者自行添加
* @param hql
* @return
*/
@SuppressWarnings("rawtypes")
public List query(Stringhql){
int index=hql.indexOf("from");
/**
* 以下语句是从hql语句中截取类名
*/
StringclassName="";//类名
StringfullclassName="";//包含包名的类名
Stringsql="";
Stringhqlsub=hql.substring(index+5);//form的长度为4,再加上空格,所以为5
className=hqlsub;
//遍历mapTables,查找类名对应的表名
for(Stringkey:mapTables.keySet()) {
if(key.contains(className)) {
tableName=mapTables.get(key);
fullclassName=key;
}
}
sql="select * from "+tableName;
ResultSet rs= helper.query(sql, null);
List<Object>lists=new ArrayList<Object>();
try {
while(rs.next()) {
Class<?>c1= Class.forName(fullclassName); //查询对象的类对象
Objects= c1.newInstance();//创建一个查询对象
Field[]fs= c1.getDeclaredFields();//获取该对象的所有属性
for(Fieldf:fs) {//遍历属性
String fname= f.getName();//获取某个属性名
StringsetMethod="set"+FirstBig(fname);//某个属性名对应的setter方法名
Method[] methods=c1.getDeclaredMethods();//获取该对象的所有方法
for(Methodm:methods) {//遍历方法
if(m.getName().equals(setMethod)) {//如果找到对应的方法
String columnName=mapColumns.get(fname);//属性名对应的字段名
m.invoke(s,rs.getObject(columnName));//执行该setter方法,给对象m赋值
break;
}
}
}
lists.add(s);//把对象存入列表
}
} catch (SQLException |ClassNotFoundException | InstantiationException | IllegalAccessExceptione) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(IllegalArgumentExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (InvocationTargetExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
return lists;
}
//把第一个字符变为大写
public String FirstBig(Stringstr) {
returnstr.substring(0,1).toUpperCase()+str.substring(1);
}
}
3.5 OrmAdd.java
package cn.com.bochy.orm;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import cn.com.bochy.dbutil.DBHepler;
/**
* 实现ORM中的添加功能
* @authorchenzhengfeng
*/
public class OrmAdd {
DBHepler helper=new DBHepler();
private static OrmImpl orm=null;
private static Map<String,String> mapColumns=null;
private Class<?>classc1;//指定要添加的对象的类类型
//通过构造方法初始化
public OrmAdd(Class<?>c1) {
this.classc1=c1;
orm=new OrmImpl();
orm.parseAnnotation(classc1);//解析注解信息
mapColumns=orm.getMapColumns();//获取属性名和字段名的对应信息
}
/**
* 通过Java的反射机制结合注解信息实现添加功能
* @param obj
* @return
*/
public boolean add(Object obj) {
//获取表名
for(String key:mapTables.keySet()) {
if(key.equals(obj.getClass().getName())) {
tableName=mapTables.get(key);
}
}
Method[] methods= obj.getClass().getDeclaredMethods();//获取添加对象中所有的方法
Field[] fileds=obj.getClass().getDeclaredFields();//获取添加对象中所有的属性
String sqlColumn="";//用于拼接要添加表中所有的字段
String sqlvalue="";//用于拼接要添加的所有值,用?代替
List<Object> parmas=newArrayList<Object>();//存储要添加的所有值
for(Fieldf:fileds)//遍历属性
for(Methodm:methods) {//遍历方法
//获取该属性对应的getter方法
if(m.getName().equals("get"+FirstBig(f.getName()))) {
Object values1;
try {
values1 = m.invoke(obj);//调用该对象的getter方法
parmas.add(values1);//把添加的值存入列表
sqlColumn+=mapColumns.get(f.getName())+",";
sqlvalue+="?,";
} catch (IllegalAccessExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (IllegalArgumentExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (InvocationTargetExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
sqlColumn=CutoutLastChar(sqlColumn);//把最后一个","去掉
sqlvalue=CutoutLastChar(sqlvalue);//把最后一个","去掉
String sql="insert into "+tableName+"("+sqlColumn+")"+" values("+sqlvalue+")";
Object[] param=parmas.toArray();//把集合列表转化为数组
return helper.noQuery(sql, param); //调用helper对象中noQuery实现添加功能
}
/**
* 去掉字符串最后一个字符
* @param str
* @return
*/
public String CutoutLastChar(Stringstr) {
returnstr.substring(0,str.length()-1);
}
/**
* 把字符串的首字符变为大写
* @param str
* @return
*/
public String FirstBig(Stringstr) {
returnstr.substring(0,1).toUpperCase()+str.substring(1);
}
}
3.6 DBHepler.java
package cn.com.bochy.dbutil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 简单的JDBC的封装
* @authorchenzhengfeng
*
*/
public class DBHepler {
private Stringurl="jdbc:mysql://localhost:3306/czf";
private Stringuser="root";
private Stringpassword="root";
public Connectionconn=null;
public PreparedStatementpstmt=null;
public ResultSetrs=null;
//1、得到连接对象
public ConnectiongetConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection(url,user, password);
} catch (ClassNotFoundExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (SQLExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
return conn;
}
//2、关闭资源
public void closeAll(){
try {
if(rs!=null){
rs.close();
}
if(pstmt!=null){
pstmt.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
//3、通用查询方法
public ResultSetquery(Stringsql,Object[] param){
try {
getConnection();
pstmt=conn.prepareStatement(sql);
if(param!=null)
for(inti=0;i<param.length;i++){
pstmt.setObject(i+1,param[i]);
}
rs=pstmt.executeQuery();
} catch (SQLExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
returnrs;
}
//4、通用非查询方法
public boolean noQuery(String sql,Object[]param){
getConnection();
int a=0;
try {
pstmt=conn.prepareStatement(sql);
if(param!=null)
for(inti=0;i<param.length;i++){
pstmt.setObject(i+1,param[i]);
}
a=pstmt.executeUpdate();
} catch (SQLExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
closeAll();
if(a>0)
return true;
else
return false;
}
}
第二部分 ORM应用
3.7 实体类Stu.java
package cn.com.bochy.entity;
import java.io.Serializable;
import cn.com.bochy.annotation.Column;
import cn.com.bochy.annotation.Table;
/**
* 实体类
* @author Administrator
*
*/
@Table("stu")//通过注解,类Stu对应表stu
public class Stu implements Serializable {
private static final long serialVersionUID = 1L;
@Column("id")//通过注解,属性名id对应字段名(列名)id
private int id;
public int getId() {
returnid;
}
public void setId(intid) {
this.id =id;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public int getAge() {
returnage;
}
public void setAge(intage) {
this.age =age;
}
@Column("name")//通过注解,属性名name对应字段名(列名)name
private String name;
@Column("age")//通过注解,属性名age对应字段名(列名)age
private int age;
public Stu() {
// TODO Auto-generatedconstructor stub
}
}
3.8 实体类Teacher.java
package cn.com.bochy.entity;
import java.io.Serializable;
import cn.com.bochy.annotation.Column;
import cn.com.bochy.annotation.Table;
@Table("teacher")//通过注解,类Teacher对应表teacher
public class Teacher implements Serializable {
private static final long serialVersionUID = 1L;
@Column(value="tid")//通过注解,属性名id对应字段名(列名)tid
private int id;
public int getId() {
returnid;
}
public void setId(intid) {
this.id =id;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public int getAge() {
returnage;
}
public void setAge(intage) {
this.age =age;
}
@Column("tname")//通过注解,属性名name对应字段名(列名)tname
private String name;
@Column("tage")//通过注解,属性名age对应字段名(列名)tage
private int age;
public Teacher() {
// TODO Auto-generatedconstructor stub
}
}
3.9 具体业务逻辑类StuBiz.java
package cn.com.bochy.biz;
import java.util.ArrayList;
import java.util.List;
import cn.com.bochy.entity.Stu;
import cn.com.bochy.orm.OrmAdd;
import cn.com.bochy.orm.OrmQuery;
/**
* 使用自定义ORM框架实现具体的业务逻辑
* @authorchenzhengfeng
*/
public class StuBiz {
OrmQuery query=new OrmQuery(Stu.class);
OrmAdd Add=new OrmAdd(Stu.class);
@SuppressWarnings("rawtypes")
List lists=new ArrayList();
@SuppressWarnings({ "rawtypes" })
/**
* 查选业务逻辑
* @return
*/
public List getAllStus(){
String hql="from Stu";
lists=query.query(hql);
return lists;
}
/**
* 添加业务逻辑
* @params
* @return
*/
public boolean add(Stu s){
return Add.add(s);
}
}
3.10 具体业务逻辑类TeacherBiz.java
package cn.com.bochy.biz;
import java.util.ArrayList;
import java.util.List;
import cn.com.bochy.entity.Stu;
import cn.com.bochy.entity.Teacher;
import cn.com.bochy.orm.OrmAdd;
import cn.com.bochy.orm.OrmQuery;
/**
* 使用自定义ORM框架实现具体的业务逻辑
* @authorchenzhengfeng
*
*/
public class TeacherBiz {
OrmQuery query=newOrmQuery(Teacher.class);
OrmAdd Add=new OrmAdd(Teacher.class);
List<Stu> lists=new ArrayList<Stu>();
@SuppressWarnings({ "unchecked", "rawtypes" })
/**
* 查选的业务逻辑
* @return
*/
public List getAllTeachers(){
String hql="from Teacher";
lists=query.query(hql);
return lists;
}
/**
* 添加的业务逻辑
* @param s
* @return
*/
public boolean addTeacher(Teacher t1) {
return Add.add(t1);
}
}
3.11 测试类TestDemo.java
package cn.com.bochy.test;
importcn.com.bochy.biz.StuBiz;
importcn.com.bochy.biz.TeacherBiz;
importcn.com.bochy.entity.Stu;
importcn.com.bochy.entity.Teacher;
public class TestDemo {
public static void main(String[] args) {
StuBiz biz=new StuBiz();
Stu s1=new Stu();
s1.setId(5);
s1.setAge(25);
s1.setName("dsew25");
biz.add(s1);
System.out.println(biz.getAllStus().size());
for(Object s:biz.getAllStus()) {
if(sinstanceof Stu) {
Stu stu=(Stu)s;
System.out.println(stu.getId()+" "+stu.getName()+" "+stu.getAge());
}
}
TeacherBiz tbiz=new TeacherBiz();
Teacher t1=new Teacher();
t1.setId(5);
t1.setName("sds5");
t1.setAge(25);
tbiz.addTeacher(t1);
System.out.println(tbiz.getAllTeachers().size());
for(Object s:tbiz.getAllTeachers()){
if(sinstanceof Teacher) {
Teacher t=(Teacher)s;
System.out.println(t.getId()+" "+t.getName()+" "+t.getAge());
}
}
}
}
四、推荐内容
http://blog.csdn.net/zhoudaxia/article/details/33731583