今天就跟大家聊聊有关如何在Java项目中使用ORM,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

一、ORM示例
1. Insert
public CompletableFutureinsert() { var obj = new sys.entities.Demo("MyName"); //构造参数为主键 obj.Age = 100; //设置实体属性的值 return obj.saveAsync(); } 
2. Update
更新单个实体(必须具备主键)
public CompletableFutureupdate(sys.entities.Demo obj) { obj.Age = 200; return obj.saveAsync(); } 
根据条件更新(必须指定条件以防误操作)
public CompletableFuture> update() {
  var cmd = new SqlUpdateCommand();
  cmd.update(e -> e.City = "Wuxi");  //更新字段
  cmd.update(e -> e.Age = e.Age + 1); //更新累加字段
  cmd.where(e -> e.Name == "Johne"); //更新的条件
  var outs = cmd.output(e -> e.Age); //更新的同时返回指定字段
  return cmd.execAsync().thenApply(rows -> {
    System.out.println("更新记录数: " + rows);
    System.out.println("返回的值: " + outs.get(0));
    return "Done.";
  });
} 3. Delete
删除单个实体(必须具备主键)
public CompletableFutureupdate(sys.entities.Demo obj) { obj.markDeleted(); //先标记为删除状态 return obj.saveAsync(); //再调用保存方法 } 
根据条件删除(必须指定条件以防误操作)
public CompletableFuture> delete() {
  var cmd = new SqlDeleteCommand();
  cmd.where(e -> e.Age < 0 || e.Age > 200);
  return cmd.execAsync();
} 4. Transaction
由于作者讨厌隐式事务,所以事务命令必须显式指定。
public CompletableFuture> transaction() {
  var obj1 = new sys.entities.Demo("Demo1");
  obj1.Age = 11;
  var obj2 = new sys.entities.Demo("Demo2");
  obj2.Age = 22;
  return DataStore.DemoDB.beginTransaction().thenCompose(txn -> { //开始事务
    return obj1.saveAsync(txn)         //事务保存obj1
      .thenCompose(r -> obj2.saveAsync(txn)) //事务保存obj2
      .thenCompose(r -> txn.commitAsync()); //递交事务
  }).thenApply(r -> "Done");
}5. Sql查询
Where条件
public CompletableFuture> query(String key) {
  var q = new SqlQuery();
  q.where(e -> e.Age > 10 && e.Age < 80);
  if (key != null)
    q.andWhere(e -> e.Name.contains(key)); //拼接条件
  return q.toListAsync(); //返回List
}  分页查询
public CompletableFuture> query(int pageSize, int pageIndex) {
  var q = new SqlQuery();
  return q.skip(pageSize * pageIndex)
    .take(pageSize)
    .toListAsync();
} 结果映射至匿名类
public CompletableFuture> query() {
  var q = new SqlQuery();
  return q.toListAsync(e -> new Object() { //返回List<匿名类>
    public final String Name = e.Name; //匿名类属性 = 实体属性表达式
    public final int  Age = e.Age + 10;
    public final String Father = e.Parent.Name;
  }).thenApply(appbox.data.JsonResult::new);
} 结果映射至继承的匿名类
public CompletableFuture> query() {
  var q = new SqlQuery();
  q.where(e -> e.Parent.Name == "Rick");
  return q.toListAsync(e -> new sys.entities.Demo() { //返回List extens Demo>
    public final String Father = e.Parent.Name;
  });
} 结果映射至树状结构列表
public CompletableFuture> tree() {
  var q = new SqlQuery();
  q.where(t -> t.Name == "Rick");
  return q.toTreeAsync(t -> t.Childs); //参数指向EntitySet(一对多成员)
} EntityRef(一对一引用的实体成员)自动Join
public CompletableFuture> query() {
  var q = new SqlQuery();
  q.where(cus -> cus.City.Name == "Wuxi");
  return q.toListAsync();
}
生成的Sql:
Select t.* From "Customer" t Left Join "City" j1 On j1."Code"=t."CityCode" 手工指定Join
public CompletableFuture> join() {
  var q = new SqlQuery();
  var j = new SqlQueryJoin();
  q.leftJoin(j, (cus, city) -> cus.CityCode == city.Code);
  q.where(j, (cus, city) -> city.Name == "Wuxi");
  return q.toListAsync();
}  子查询
public CompletableFuture> subQuery() {
  var sq = new SqlQuery();
  sq.where(s -> s.ParentName == "Rick");
  
  var q = new SqlQuery();
  q.where(t -> DbFunc.in(t.Name, sq.toSubQuery(s -> s.Name)));
  return q.toListAsync();
}  GroupBy
public CompletableFuture> groupBy() {
  var q = new SqlQuery();
  q.groupBy(t -> t.ParentName) //多个可重复
    .having(t -> DbFunc.sum(t.Age) > 10);
  return q.toListAsync(t -> new Object() {
    public final String group = t.ParentName == null ? "可怜的孩子" : t.ParentName;
    public final int totals = DbFunc.sum(t.Age);
  }).thenApply(appbox.data.JsonResult::new);
} 二、实现原理
其实以上的示例代码并非最终运行的代码,作者利用Eclipse jdt将上述代码在编译发布服务模型时分析转换为最终的运行代码,具体过程如下:
1. jdt分析服务虚拟代码生成AST抽象语法树;
2. 遍历AST树,将实体对象的读写属性改写为getXXX(), setXXX();
var name = obj.Name; //读实体属性 obj.Name = "Rick"; //写实体属性
改写为:
var name = obj.getName();
obj.setName("Rick");3. 遍历AST树,将查询相关方法的参数转换为运行时表达式;
public CompletableFuture> query(String key) {
  var q = new SqlQuery();
  q.where(e -> e.Manager.Name + "a" == key + "b");
  return q.toListAsync();
} 转换为:
public CompletableFuture> query(String key) {
  var q = new appbox.store.query.SqlQuery<>(-7018111290459553788L, SYS_Employee.class);
  q.where(e -> e.m("Manager").m("Name").plus("a").eq(key + "b"));
  return q.toListAsync();
}4. 根据服务模型使用到的实体模型生成相应实体的运行时代码;
5. 最后编译打包服务模型的字节码。
以上请参考源码的ServiceCodeGenerator及EntityCodeGenerator类。
三、性能与小结
作者写了个简单查询的服务,测试配置为MacBook主机(wrk压测 + 数据库)->4核I7虚拟机(服务端),测试结果如下所示qps可达1万,已包括实体映射转换及序列化传输等所有开销。这里顺便提一下,由于框架是全异步的,所以没有使用传统的JDBC驱动,而是使用了jasync-sql(底层为Netty)来驱动数据库。
wrk -c200 -t2 -d20s -s post_bin.lua http://10.211.55.8:8000/api Running 20s test @ http://10.211.55.8:8000/api 2 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 18.97ms 5.84ms 89.15ms 81.55% Req/Sec 5.32k 581.92 6.48k 65.00% 211812 requests in 20.02s, 36.76MB read Requests/sec: 10578.90 Transfer/sec: 1.84MB
看完上述内容,你们对如何在Java项目中使用ORM有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。
文章名称:如何在Java项目中使用ORM-创新互联
文章网址:http://www.scyingshan.cn/article/ppidi.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 