zoukankan      html  css  js  c++  java
  • 系统架构一一ORM的应用

    在没有ORM的时代,我们直接从数据库中返回完整的数据集,然后通过键值对取出相应字段的数据,当然更要需要,取出的数据还要转换成编程语言相应的类型,再进行数据的操作。这种方式存储数据干脆直接,还可以利用Sql语句进行查询的优化,有些复杂的查询逻辑还可以编写成存储过程,充分利用数据库的性能,降低客户端的压力。

    //ADO.NET示例
            string connectionString =
                "Data Source=(local);Initial Catalog=Northwind;"
                + "Integrated Security=true";
    
            // Provide the query string with a parameter placeholder.
            string queryString =
                "SELECT ProductID, UnitPrice, ProductName from dbo.products "
                    + "WHERE UnitPrice > @pricePoint "
                    + "ORDER BY UnitPrice DESC;";
    
            // Specify the parameter value.
            int paramValue = 5;
    
            // Create and open the connection in a using block. This
            // ensures that all resources will be closed and disposed
            // when the code exits.
            using (SqlConnection connection =
                new SqlConnection(connectionString))
            {
                // Create the Command and Parameter objects.
                SqlCommand command = new SqlCommand(queryString, connection);
                command.Parameters.AddWithValue("@pricePoint", paramValue);
    
                // Open the connection in a try/catch block.
                // Create and execute the DataReader, writing the result
                // set to the console window.
                try
                {
                    connection.Open();
                    SqlDataReader reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine("	{0}	{1}	{2}",
                            reader[0], reader[1], reader[2]);
                    }
                    reader.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.ReadLine();
            }
        }
    

    但直接利用Sql返回数据的方式,有个最大的问题就是可读性太差。首先程序代码中有很多拼合SQL的代码,以及数据迭代的代码。因为没有限制,还可以一边查询,一边处理业务逻辑,数据库操作代码和客户端代码混合一起,数量一上来,就变成天书了。所以有聪明的人,就把一些比较通用的部分分离出来,比如构建一个DBHelper,把数据库连接部分单独拉出来,再提供一些通用的查询函数,微软的企业库就是一个比较典型的实现。但这样也只是可以稍微偷懒一点,事务上好控制点。

    //利用EntLib返回一个数据集。
            Database db = DatabaseFactory.CreateDatabase("ConStr");
                string sql = "select * from Brand";
                DbCommand cmd = db.GetSqlStringCommand(sql);
     
                DataSet set = db.ExecuteDataSet(cmd);
    
    

    后来有了J2EE框架,里边定义了各种Bean,有一种Bean叫Entity Bean,这个Entity Bean基本上跟数据库一一对应的,可序列化,可用于远程传递数据的无状态类。也就是说J2EE里边,要求事先将数据记录转换成存值的对象,再通过Session Bean(也就是Bussiness Object、BO)的调用返回数据的Copy,所有的数据库存取的代码,限制在了持久层(也就是DataAccess Layer,DataAccess Object、DAO),按照这种思维一起,应用程序的结构就很清晰了,代码的可读性也提升了,代码的可维护性也就增强了,然后就可以往系统中增加更多的功能了。

    虽说数据库操作放在了持久层里,但数据对像的生成还是要程序员去写的,一个表有上百个字段,那你就得写上几倍于数据表字段数量的get/set,以前直接写Sql是根据需要来做Select的投影,需要什么就查什么,而现在则要全部做个映射,这个工作量可想而知还是不小的。于是有人把这部分操作弄成了一个独立的组件,开放出相应的接口给下游程序调用,当然目标是Sql无关的,带来的好处就是干净,少了很多数据库层面的拼装。

    //EntityFramework的一个例子
        public abstract class QueryBase<T> : IQueryBase<T> where T : EntityBase
        {
            protected AppDataContext DataContext { get; set; }
    
            public List<T> FindByPage()
            {
                return DataContext.Set<T>().ToList();
            }
        }
        
    
    
    

    对应的Sql

    select * from T --T must be replaced by actual table name
    

    ORM还有个特性就是实现数据库的无关性。上述Entity Framework的例子里,因为不需要写出Sql的具体实现,所以可以通过规范,使用不同的数据库驱动,实现同一套代码,在不同的数据库上运行。

    在Setup.cs中设置数据库配置。

    
                services.AddDbContext<AppDataContext>(
                    options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
                    );
    
    

    在Jpa中指定数据库方言

    	@Bean
    	public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws IOException, PropertyVetoException, SQLException {
    		LocalContainerEntityManagerFactoryBean efactory = new LocalContainerEntityManagerFactoryBean();
    		efactory.setDataSource(dataSource());
    		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    		jpaVendorAdapter.setGenerateDdl(true);
    		jpaVendorAdapter.setDatabase(Database.MYSQL);
    		jpaVendorAdapter.setShowSql(true);
    		
    		efactory.setJpaVendorAdapter(jpaVendorAdapter);
    		efactory.setPersistenceProviderClass(org.hibernate.jpa.HibernatePersistenceProvider.class);
    		efactory.setPersistenceUnitName("test");
    		efactory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
    
    		return efactory;
    	}
    

    ORM另一个目的就是就是数据操作面向对象话,消除了面向过程的Sql语句的干扰,编程语言就可以做许多神奇的事情来。比如springdata中,只需要定义接口,然后通过动态代码加上依赖注入的方式,就可以实现持久层的实现:

    public interface AccountRepository extends JpaRepository<Account, String> {
    	Account findByUsername(String username);
    }
    

    当然ORM也有很多不足,比如无形中增加了许多配置项,也增加了学习成本,查询性能上没法跟SQL相比,聚合查询不太容易实现等。

  • 相关阅读:
    git常用命令及常见问题解析
    如何让一个sprite绕一个点旋转,同时又可以实现指定旋转角度并慢慢停下的效果
    webpack打包,同时将ES6转为ES5,初探
    测试网站接口,nginx篇
    Phaserjs V2的state状态解析及技巧
    Phaserjs怎样用ES6开发游戏
    PIXI屏幕自适应以及强制横屏
    CSS性能优化新属性:will-change
    div,css&table布局有哪些区别
    防止js全局变量污染方法总结
  • 原文地址:https://www.cnblogs.com/icoolno1/p/12853018.html
Copyright © 2011-2022 走看看