ORM框架是什么
对象关系映射(Object Relational Mapping),目前数据库是关系型数据库 , ORM 主要是把数据库中的关系数据映射成为程序中的对象。ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM中间件有:Hibernate,Mybatis等。 这样能够让程序员更多的关注业务编程,而不用浪费在SQL语句的编写上。
映射方式:注解,xml
ORM的方法论基于三个核心原则:
· 简单:以最基本的形式建模数据。
· 传达性:数据库结构被任何人都能理解的语言文档化。
· 精确性:基于数据模型创建正确标准化了的结构。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
下面就开始自己ORM框架编写,源码可在github上找到:
首先在数据库创建一张user_info表:
有id,name,birthday三个字段。我们要对数据库这张表进行操作的话,就要创建一个与它对应的entity对象,通过操作实体类对象达到数据库表的操作。
@Table("user_info")
public class UserInfo {
@Column
private Integer id;
@Column
private String name;
@Column
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
那么我们怎么让表和对象产生对应关系呢?我们可以通过在entity对象上添加注解,让对象和数据库表关系映射。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value() default "";
}
映射关系已经有了,接下来就来操作对象吧
public interface UserDao {
int insert(UserInfo userInfo);
}
public class UserDaoImpl implements UserDao {
@Override
public int insert(UserInfo userInfo) {
return session.insert(userInfo);
}
}
你会发现根本不行,因为这个映射关系只是我们自己定义的,接下来就是这个ORM框架核心的部分了,就是让我们自定义的注解能够生效,生成想要的sql语句:
public interface SqlSession {
<T> int insert(T entity);
}
public class SqlSessionImpl implements SqlSession {
private DataSource dataSource;
public SqlSessionImpl(){
this.dataSource = new DataSourceImpl();
}
@Override
public <T> int insert(T entity) {
int row = 0;
if(entity == null){
throw new ORMException("实体对象为空");
}
//构建SQL语句
StringBuilder sql = new StringBuilder();
//参数列表
List<Object> parameters = new ArrayList<>();
builderSqlByEntity(entity,sql,parameters);
try(Connection connect = dataSource.getDataSource();
PreparedStatement statement = connect.prepareStatement(sql.toString())){
if(parameters.size() > 0){
for(int i = 0; i < parameters.size(); i++){
statement.setObject(i+1, parameters.get(i));
}
}
//执行SQL
row = statement.executeUpdate();
}catch(Exception e){
throw new ORMException("执行SQL语句出错:" + e.getMessage());
}
return row;
}
@SuppressWarnings("unused")
private<T> void builderSqlByEntity(T entity,StringBuilder sql,List<Object> parameters){
//根据实体对象生成SQL语句
Class<?> clazz = entity.getClass();
//如果table没有指定名字,则用类名代替
String tableName = clazz.getSimpleName();
if(clazz.isAnnotationPresent(Table.class)){
Table table = clazz.getAnnotation(Table.class);
if(!"".equals(table.value())){
tableName = table.value();
}
}
sql.append("insert into ").append(tableName).append("(");
Field[] fields = clazz.getDeclaredFields();
try{
for(Field field : fields){
String columnName = field.getName();
if(field.isAnnotationPresent(Column.class)){
Column column = field.getAnnotation(Column.class);
if(!"".equals(column.value())){
columnName = column.value();
}
}
//属性描述器
PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
Method method = descriptor.getReadMethod();
Object object = method.invoke(entity);
if(object != null){
sql.append(columnName + ",");
parameters.add(object);
}
}
sql.deleteCharAt(sql.length()-1).append(") values (");
for(Object obj : parameters){
sql.append("?,");
}
sql.deleteCharAt(sql.length()-1).append(")");
System.out.println(sql);
}catch(Exception e){
throw new ORMException("执行SQL语句出错:" + e.getMessage());
}
}
}
public class UserDaoImpl implements UserDao {
private SqlSession session = new SqlSessionImpl();
@Override
public int insert(UserInfo userInfo) {
return session.insert(userInfo);
}
}
这样我们就能通过在entity对象上添加自定义的注解与数据库表产生映射关系,操作实体对象就能对表进行增删改查的操作。自己编写的简单ORM框架就完成了。