有没有一个轻量级的ORM框架看源码来学习如何设计ORM的

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
有没有一个轻量级的ORM框架?就是JAVA的,我想学习一下。不要mybatis那种很大的。个人写的就可以了。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
nutz-dao 非常精简高效的ORM框架,分析源码对你学习很有帮助。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:轻量级ORM框架ActiveJDBC介绍
这款开源轻量级的ORM框架,看了下例子,感觉非常小巧轻量简单。
public class Main {
&&& public
static void main(String[] args) {
new DB("corporation").open("com.mysql.jdbc.Driver",
"jdbc:mysql://localhost/test",
&&&&&&&&&&&&&&&
"root", "");
new DB("university").open("oracle.jdbc.driver.OracleDriver",
&&&&&&&&&&&&&&&
"jdbc:oracle:thin:@localhost:1521:xe",
&&&&&&&&&&&&&&&
"activejdbc", "activejdbc");
Employee.deleteAll();
Student.deleteAll();
Employee.createIt("first_name", "John", "last_name", "Doe");
Employee.createIt("first_name", "Jane", "last_name",
Student.createIt("first_name", "Mike", "last_name", "Myers");
Student.createIt("first_name", "Steven", "last_name",
"Spielberg");
System.out.println("*** Employees ***");
Employee.findAll().dump();
System.out.println("*** Students ***");
Student.findAll().dump();
new DB("corporation").close();
new DB("university").close();
ActiveJDBC 是一个快速和轻量级的 Java 的 ORM
小型框架,语法简单易于理解,同时支持多数据库链接。ActiveJDBC 的文档()非常完善。基于以下原则设计:
惯例重于配置(无配置)
拥有 SQL 知识就足够了
轻量级而且直观的代码
无持久层管理
无 proxying
有关ActiveJDBC的特性的官方说明在这里:
项目发布在网站上,地址是:&可以使用SVN
将项目Check out下来。
ActiveJDBC
项目是使用Maven进行构建和管理JAR包的,具体怎样使用Maven来进行构建,它的网站上写得很详细,Maven本身也很简单。这里我只是记录下我的操作步骤,使用手动构建的。
1. 创建测试工程,引入必要的JAR包
在MyEclipse里新建一个WEB工程(JAVA工程也可以), 然后,引入所需要的JAR包
这些JAR包可以到&这里下载,最新的JAR包在页面最下面。上面这些JAR包缺一不可,我首先引入的是activejdbc包,然后根据ClassNotFoundException挨个导入的。
接着可以看下ActiveJDBC文档的页,写得非常简洁,可以让你很快上手。
2. 创建数据库和表
建表语句是
&&& create
&&& create table
&&& id int(32)
default not null auto_increment primary key,
&&& first_name
varchar(65),
&&& last_name
varchar(65)
AJ的表名与Model名是有命名约定的,比如Model名为Employee,对应表名为employees。
3. 新建一个POJO
内容如下:
&&& package
&&& import
activejdbc.M
&&& public class
Employee extends Model {
没有Getters和Setters?
没错,不需要,而且ActiveJDBC也不推荐。它是利用了JAVA的反射机制来进行识别的,不仅不必写Getters和Setters,连同
fields也不必写,只要你事先建立好表,AJ会自动为你建立映射。而且也不必配置表名与POJO间的对应关系,因为AJ遵循“约定&配置”的原则,可以省掉配置文件,非常方便简单。
3. 建立一个创建Instrumentation的文件
Instrumentation是对已经编译好的POJO们进行一下处理,添加了父类的静态方法,这样才可以像下面这样使用:
List&Person& retirees = Person.where("age &= ?", 65);
否则,AJ不会知道将要操作的表或数据库,因为静态方法是属于类而不是对象的。这样虽然稍微麻烦点,但是好处也是挺不错的,它不必像其它ORM框架一样,需要使用第三个类来进行管理,比如JPA使用的PersistentManager和Hibernate
使用的Session。
尽管AJ需要增加一步额外的构建过程,但它使API的设计更加直观和简洁。
还有一点要说明的是,Instrumentation的创建也是很快的,而且只需要在程序编译的时候进行创建即可。官方文档中说50-60个models只需要5-7s,一般的小型程序(10个以内models的程序)只需要1-2秒即可完成。
官方文档只主要介绍了使用Maven,Ant,和StandAlone三种方式,我使用的是另外一种,JAVA程序实现的。只需要创建一个工具类,然后在编译之后,运行之前调用一下这个类的make方法即可。
&&& package
&&& import
activejdbc.instrumentation.I
&&& public class
MakeInstrumentationUtil {
&&& public
static void make() {
Instrumentation instrumentation = new Instrumentation();
instrumentation.setOutputDirectory(ClassLoader
.getSystemResource(“”).getPath());
instrumentation.instrument();
&&& } catch
(Exception e) {
e.printStackTrace();
4. 创建测试类。
package cn.ijser.
import activejdbc.B
import cn.ijser.pojo.E
import cn.ijser.utils.MakeInstrumentationU
public class Test {
public static void main(String[] args) {
MakeInstrumentationUtil.make(); # 这里创建Instrumentation
Base.open(“com.mysql.jdbc.Driver”,
“jdbc:mysql://localhost/activejdbc”,
“root”, “sa”);
Employee e = new Employee();
e.set(“first_name”, “John”);
e.set(“last_name”, “ijse”);
AJ的具体使用方法,可以查看AJ的文档,上面这个测试代码只是向数据库的employees表中写入了一条记录。
转载地址:
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。.net下开源轻量级ORM框架Dapper扩展系列1
我的图书馆
.net下开源轻量级ORM框架Dapper扩展系列1
& & &轻量级ORM框架Dapper相信很多人了解,也用过,可能也有很多人可能还不知道
Dapper官网:
我在网上复制一下别人对Dapper的描述:
Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件。文件见下。编译后就40K的一个很小的Dll.
Dapper很快,有多快。实验下就知道了。官方给了点测试包,想玩的时候就去测试下。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
Dapper支持什么数据库。Dapper支持Mysql,SqlLite,Mssql2000,Mssql2005,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db.
Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。
Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高。
Dapper支持net2.0,3.0,3.5,4.0。
Dapper的语法是这样的。语法十分简单。并且无须迁就数据库的设计。
为什么要扩展Dapper:
了解Dapper都知道,在书写代码时,我们还是会手动写SQL,扩展的目的就是在完全不改变dapper源代码和使用基础上,进行一次封闭,达到零SQL,实现完全对象操作。
接下来,我们开始Dapper的扩展之旅第一章。。。
下载Dapper后,我们新建类库项目:DapperEx ,并把Dapper项目加载到项目中:
1.在DapperEx 中添加Dapper引用 ,如下:
2.为了存储数据库类型,以及根据数据库类型,使用不同的参数化操作数据库,添加一个DbBase类:
using System.Collections.G
using System.C
using System.D
using System.L
using System.T
namespace Dapper
public class DbBase : IDisposable
private string paramPrefix = "@";
private string providerName = "System.Data.SqlClient";
private IDbConnection dbC
private DbProviderFactory dbF
private DBType _dbType = DBType.SqlS
public IDbConnection DbConnecttion
return dbC
public string ParamPrefix
return paramP
public string ProviderName
return providerN
public DBType DbType
return _dbT
public DbBase(string connectionStringName)
var connStr = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionS
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName))
providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderN
throw new Exception("ConnectionStrings中没有配置提供程序ProviderName!");
dbFactory = DbProviderFactories.GetFactory(providerName);
dbConnecttion = dbFactory.CreateConnection();
dbConnecttion.ConnectionString = connS
dbConnecttion.Open();
SetParamPrefix();
private void SetParamPrefix()
string dbtype = (dbFactory == null ? dbConnecttion.GetType() : dbFactory.GetType()).N
// 使用类型名判断
if (dbtype.StartsWith("MySql")) _dbType = DBType.MyS
else if (dbtype.StartsWith("SqlCe")) _dbType = DBType.SqlServerCE;
else if (dbtype.StartsWith("Npgsql")) _dbType = DBType.PostgreSQL;
else if (dbtype.StartsWith("Oracle")) _dbType = DBType.O
else if (dbtype.StartsWith("SQLite")) _dbType = DBType.SQL
else if (dbtype.StartsWith("System.Data.SqlClient.")) _dbType = DBType.SqlS
// else try with provider name
else if (providerName.IndexOf("MySql", StringComparison.InvariantCultureIgnoreCase) &= 0) _dbType = DBType.MyS
else if (providerName.IndexOf("SqlServerCe", StringComparison.InvariantCultureIgnoreCase) &= 0) _dbType = DBType.SqlServerCE;
else if (providerName.IndexOf("Npgsql", StringComparison.InvariantCultureIgnoreCase) &= 0) _dbType = DBType.PostgreSQL;
else if (providerName.IndexOf("Oracle", StringComparison.InvariantCultureIgnoreCase) &= 0) _dbType = DBType.O
else if (providerName.IndexOf("SQLite", StringComparison.InvariantCultureIgnoreCase) &= 0) _dbType = DBType.SQL
if (_dbType == DBType.MySql && dbConnecttion != null && dbConnecttion.ConnectionString != null && dbConnecttion.ConnectionString.IndexOf("Allow User Variables=true") &= 0)
paramPrefix = "?";
if (_dbType == DBType.Oracle)
paramPrefix = ":";
public void Dispose()
if (dbConnecttion != null)
dbConnecttion.Dispose();
public enum DBType
SqlServer,
SqlServerCE,
PostgreSQL,
此类功能利用DbProviderFactories实现数据源连接接口IDbConnection,通过数据库判断设置参数前缀为@、?、:的一种。
3.和大多数实体映射一样,为了更方便的操作数据库,我们添加几个特性,来实现实体与数据库表的映射关系:
BaseAttribute:特性基类
using System.Collections.G
using System.L
using System.T
namespace Dapper
public class BaseAttribute:Attribute
/// &summary&
/// 别名,对应数据里面的名字
/// &/summary&
public string Name { get; set; }
ColumnAttribute:字段列特性
using System.Collections.G
using System.L
using System.T
namespace Dapper
/// &summary&
/// 列字段
/// &/summary&
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ColumnAttribute : BaseAttribute
/// &summary&
/// 自增长
/// &/summary&
public bool AutoIncrement { get; set; }
public ColumnAttribute()
AutoIncrement = false;
/// &summary&
/// 是否是自增长
/// &/summary&
/// &param name="autoIncrement"&&/param&
public ColumnAttribute(bool autoIncrement)
AutoIncrement = autoI
IdAttribute:主键列特性
using System.Collections.G
using System.L
using System.T
namespace Dapper
/// &summary&
/// &/summary&
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class IdAttribute : BaseAttribute
/// &summary&
/// 是否为自动主键
/// &/summary&
public bool CheckAutoId { get; set; }
public IdAttribute()
this.CheckAutoId = false;
/// &summary&
/// &/summary&
/// &param name="checkAutoId"&是否为自动主键&/param&
public IdAttribute(bool checkAutoId)
this.CheckAutoId = checkAutoId;
IgnoreAttribute:忽略列特性
using System.Collections.G
using System.L
using System.T
namespace Dapper
/// &summary&
/// 忽略字段
/// &/summary&
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class IgnoreAttribute:BaseAttribute
TableAttribute:数据库表特性
using System.Collections.G
using System.L
using System.T
namespace Dapper
/// &summary&
/// 数据库表
/// &/summary&
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TableAttribute : BaseAttribute
4.接下来建立一个生成SQL时参数里面的列名和对应值名称的对应类:ParamColumnModel
using System.Collections.G
using System.L
using System.T
namespace Dapper
/// &summary&
/// 生成SQL时参数里面的列名和对应值名称
/// &/summary&
public class ParamColumnModel
/// &summary&
/// 数据库列名
/// &/summary&
public string ColumnName { get; set; }
/// &summary&
/// 对应类属性名
/// &/summary&
public string FieldName { get; set; }
5.建立一个公共类,方便对特性、属性进行操作和取值等操作Common
using System.Collections.G
using System.L
using System.Linq.E
using System.T
using System.Text.RegularE
namespace DapperEx
public class Common
/// &summary&
/// 获取对象对应数据库表名
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &returns&&/returns&
public static string GetTableName&T&()
var ty = typeof(T);
var arri = ty.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is TableAttribute && (!string.IsNullOrEmpty((arri as BaseAttribute).Name)))
return (arri as BaseAttribute).N
return ty.N
/// &summary&
/// 在没有指定排序时,获取一个默认的排序列
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &returns&&/returns&
public static string GetDefaultOrderField&T&()
var name = "";
foreach (var propertyInfo in typeof(T).GetProperties())
var arri = propertyInfo.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is IgnoreAttribute)
arri = null;
name = (arri == null || string.IsNullOrEmpty((arri as BaseAttribute).Name)) ? propertyInfo.Name : (arri as BaseAttribute).N
/// &summary&
/// 获取要执行SQL时的列,添加和修改数据时
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &returns&&/returns&
public static IList&ParamColumnModel& GetExecColumns&T&() where T : class
var columns = new List&ParamColumnModel&();
foreach (var propertyInfo in typeof(T).GetProperties())
var arri = propertyInfo.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is IgnoreAttribute)
arri = null;
else if (arri is IdAttribute)
if ((arri as IdAttribute).CheckAutoId)
arri = null;
else if (arri is ColumnAttribute)
if ((arri as ColumnAttribute).AutoIncrement)
arri = null;
string name = (arri == null || string.IsNullOrEmpty((arri as BaseAttribute).Name)) ? propertyInfo.Name : (arri as BaseAttribute).N
columns.Add(new ParamColumnModel() { ColumnName = name, FieldName = propertyInfo.Name });
/// &summary&
/// 获取对象的主键标识列
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &param name="PropertyName"&对应实体属性名&/param&
/// &returns&&/returns&
public static string GetPrimaryKey&T&(out string PropertyName) where T : class
string name = "";
PropertyName = "";
foreach (var propertyInfo in typeof(T).GetProperties())
var arri = propertyInfo.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is IdAttribute)
name = (arri == null || string.IsNullOrEmpty((arri as BaseAttribute).Name)) ? propertyInfo.Name : (arri as BaseAttribute).N
PropertyName = propertyInfo.N
if (string.IsNullOrEmpty(PropertyName))
throw new Exception("没有任何列标记为主键特性");
/// &summary&
/// 通过属性名获取对应的数据列名
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &param name="propertyName"&&/param&
/// &returns&&/returns&
public static string GetExecCloumName&T&(string propertyName) where T : class
var propertyInfo = typeof(T).GetProperty(propertyName);
var arri = propertyInfo.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is IgnoreAttribute)
arri = null;
string name = (arri == null || string.IsNullOrEmpty((arri as BaseAttribute).Name)) ? propertyInfo.Name : (arri as BaseAttribute).N
/// &summary&
/// 通过表达示树获取属性名对应列名
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &param name="expr"&&/param&
/// &returns&&/returns&
public static string GetNameByExpress&T&(Expression&Func&T, object&& expr) where T : class
var pname = "";
if (expr.Body is UnaryExpression)
var uy = expr.Body as UnaryE
pname = (uy.Operand as MemberExpression).Member.N
pname = (expr.Body as MemberExpression).Member.N
var propertyInfo = typeof(T).GetProperty(pname);
var arri = propertyInfo.GetCustomAttributes(typeof(BaseAttribute), true).FirstOrDefault();
if (arri is IgnoreAttribute)
throw new Exception(string.Format("{0}不能进行SQL处理", pname));
string name = (arri == null || string.IsNullOrEmpty((arri as BaseAttribute).Name)) ? propertyInfo.Name : (arri as BaseAttribute).N
/// &summary&
/// 字符串中连续多个空格合并成一个空格
/// &/summary&
/// &param name="str"&&/param&
/// &returns&&/returns&
public static string UnitMoreSpan(string str)
Regex replaceSpace = new Regex(@"\s{1,}", RegexOptions.IgnoreCase);
return replaceSpace.Replace(str, " ").Trim();
6.有了以上基础,现在开始进行扩展操作,新建DapperEx类:
本系列,我们先扩展两个方法:添加一个实体 和 批量添加
代码比较简单:
using System.Collections.G
using System.L
using System.T
using System.D
using DapperEx;
namespace Dapper
public static class DapperEx
/// &summary&
/// 扩展插入数据
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &param name="db"&&/param&
/// &param name="t"&&/param&
/// &param name="useTransaction"&&/param&
/// &param name="commandTimeout"&&/param&
/// &param name="commandType"&&/param&
/// &returns&&/returns&
public static bool Insert&T&(this DbBase dbs, T t, bool useTransaction = false, int? commandTimeout = null) where T : class,new()
var db = dbs.DbC
IDbTransaction tran = null;
if (useTransaction)
tran = db.BeginTransaction();
var result = false;
var tbName = Common.GetTableName&T&();
var columns = Common.GetExecColumns&T&();
var flag = db.Execute(CreateInertSql(tbName, columns, dbs.ParamPrefix), t, tran, commandTimeout);
if (tran != null)
result = true;
tran.Rollback();
return flag == 1;
/// &summary&
/// 批量插入
/// &/summary&
/// &typeparam name="T"&&/typeparam&
/// &param name="db"&&/param&
/// &param name="lt"&&/param&
/// &param name="useTransaction"&&/param&
/// &param name="commandTimeout"&&/param&
/// &returns&&/returns&
public static bool InsertBatch&T&(this DbBase dbs, IList&T& lt, bool useTransaction = false, int? commandTimeout = null) where T : class,new()
var db = dbs.DbC
IDbTransaction tran = null;
if (useTransaction)
tran = db.BeginTransaction();
var result = false;
var tbName = Common.GetTableName&T&();
var columns = Common.GetExecColumns&T&();
var flag = db.Execute(CreateInertSql(tbName, columns, dbs.ParamPrefix), lt, tran, commandTimeout);
if (tran != null)
result = true;
tran.Rollback();
return flag == lt.C
/// &summary&
/// 组装插入语句
/// &/summary&
/// &param name="tbName"&&/param&
/// &param name="colums"&&/param&
/// &returns&&/returns&
private static string CreateInertSql(string tbName, IList&ParamColumnModel& colums, string ParamPrefix)
StringBuilder sql = new StringBuilder();
sql.Append(string.Format("INSERT INTO {0}(", tbName));
for (int i = 0; i & colums.C i++)
if (i == 0) sql.Append(colums[i].ColumnName);
else sql.Append(string.Format(",{0}", colums[i].ColumnName));
sql.Append(")");
sql.Append(" VALUES(");
for (int i = 0; i & colums.C i++)
if (i == 0) sql.Append(string.Format("{0}{1}", ParamPrefix, colums[i].FieldName));
else sql.Append(string.Format(",{0}{1}", ParamPrefix, colums[i].FieldName));
sql.Append(") ");
return sql.ToString();
今天要讲的都已经完成,接下来,我们进行使用测试:
在解决方案中添加一个测试库:DapperExTest,并在测试库中添加一个本地数据库:dbSqlCeEx.sdf,并在数据库中中添加一个表:Account
注意最后个一字段。Flag是一个字增长列.
在测试库中添加一个应用程序配置文件:App.config,并修改成自己相应的连接数据库字符串
在测试库中添加一个相应的实体类:Account
namespace DapperExTest
public class Account
public virtual string Id { get; set; }
public virtual string Name { get; set; }
public virtual string Password { get; set; }
public virtual string Email { get; set; }
public virtual DateTime CreateTime { get; set; }
public virtual int Age { get; set; }
[Column(true)]
public virtual int Flag { get; set; }
public virtual string AgeStr
return "年龄:" + A
上述工作完成后,在测试类UnitTest1中添加如下代码:
public string connectionName = "strSqlCe";
public DbBase CreateDbBase()
return new DbBase(connectionName);
现在我们对添加功能,进行测试,添加方法:
[TestMethod]
public void Insert()//插入一条数据
var model = new Account()
Name = "张三1",
Password = "123456",
Email = "",
CreateTime = DateTime.Now,
using (var db = CreateDbBase())
var result = db.Insert&Account&(model);
if (result)
Console.WriteLine("添加成功");
Console.WriteLine("添加失败");
右键运行测试,测试成功,成功添加一条数据:
现在测试批量添加:
[TestMethod]
public void InsertBatch()//插入多条数据
var list = new List&Account&();
for (int i = 2; i & 21; i++)
var model = new Account()
Id = i.ToString(),
Name = "张三" + i.ToString(),
Password = "123456",
Email = "",
CreateTime = DateTime.Now,
list.Add(model);
using (var db = CreateDbBase())
var result = db.InsertBatch&Account&(list, true);
if (result)
Console.WriteLine("添加成功");
Console.WriteLine("添加失败");
运行完成后,查看数据库:
成功!!!
今天的扩展到此结束,后续系列将会对修改、批量修改、删除、批量删除、查询、分页进行扩展
希望大家多多关注,觉得对自己有所帮助或有意见的,欢迎留言,觉得不错的,不要吝啬你的鼠标,点点支持,点点推荐,谢谢啦!!!
本系列源码:/s/1dDh4T7F
TA的最新馆藏
喜欢该文的人也喜欢

我要回帖

 

随机推荐