ebean  orm框架,其作者觉得hibernate的bean管理会话管理。难以在短时间明确,就自己搞了一套,就成了如今的ebean。

ebean被一些开发人员这觉得是一把瑞士军刀。能够看出一些程序猿对ebean的高度评价。以下是一些ebean的特点总结

1.简单易于学习和使用(简化hibernate,仅仅有一个jar包)

     2.使用标准的JPA annotation,即: @@OneToMany等。

     3.提供Sessionless API,也就是说没有merge,flush等方法。(这也是Ebean与Hibernatet等ORM的重要差别之中的一个);

     4.通过Autofetch*进行自己主动查询调优。支持级联保存和删除。

     5.链式查询语言

     6.L1、L2 缓存

     7.集成Lucene文本搜索。

以下是一段使用ebean的代码例子

package models;

import com.avaje.ebean.Ebean;

import com.avaje.ebean.annotation.Formula;

import com.avaje.ebean.annotation.Transactional;

import com.avaje.ebean.cache.ServerCacheManager;

import play.data.validation.Constraints;

import play.db.ebean.Model;

import util.Util;





import javax.persistence.*;

import java.util.List;





/**

 * Created by wangjun on 14-3-26.

 */

@Entity // ebean 所用的注解是jpa

//@Table(name = "user")

public class User extends Model {





    @Id //@EmbeddedId 复杂id

    public Long id; //默认命名约定:first_name maps to firstName

    @Constraints.Required

    public String username;

    //@Column(name = "password")

    public String password;

    @ManyToOne(cascade = CascadeType.ALL)

    //会载入address_id ,但不会载入整个address,这个和hibernate有差别。Ebean的延迟载入对于性能的影响不打,默认EAGER。最好打开

    public Address address; //出身地

    /*@OneToOne

    public User mate;//配偶*/

   /* @OneToMany(cascade = CascadeType.PERSIST)

    public List<Address> addresses;//曾居住地  会在address端要求user_id 字段。能够用?ManyToMany取代*/

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)

//cascade = CascadeType.ALL 级联情况下会自己主动插入car个中间表数据,默认不级联 。对于一些级联更新非常是有必要

    public List<Car> cars;

    @Formula(select = "(select count(*) from user_car c where c.user_id = ${ta}.id )")

    // 计算拥有车的数量 ${ta} 代表表的别名 ,还能够写join

    public int carSize;





    //@Transient









    //会满足上述条件后在调用此方法,全局验证

    public String validate() {

        if (username.equals("1")) {

            return "Invalid email or password";

        }

        return null;

    }





   /* public List<ValidationError> validate() {

        if ( username.equals("1")) {

            return null;

        }

        return null;

    }





    public Map<ValidationError> validate() {

        if ( username.equals("1")) {

            return null;

        }

        return null;

    }*/





    public static Model.Finder<Long, User> find = new Model.Finder(Long.class, User.class);





    //============自己主动抓取測试==start=================

    public static User findById(Long id) {

        User user = find.byId(id); //不抓取car,LAZY不select address_id

        return user;

    }





    public static User findById(Long id, int loadType) {

        User user = find.byId(id); //不抓取car,不抓取address

        String name = null;

        int size = 0;

        if (loadType == 1)

            name = user.address.province; //每次都会载入user

        else if (loadType == 2)

            size = user.cars.size(); //每次都会载入car

        Util.report(name);

        Util.report(size + "");

        return user;

    }









    //连表查询測试

    public static User findByIdLoadAddress(Long id) {

        return find.fetch("address").fetch("cars").where().eq("id", id).findUnique(); // fetch= 生成join查询 不用fetch延迟载入,且不会生成join查询;

    }





    /**

     * *

     * TxType Descriptions

     * TxType Description

     * REQUIRED Runs in a Transaction. Will use an existing transaction if it exists, otherwise will create a new Transaction.

     * REQUIRES_NEW Runs in a new Transaction. If a current transaction exists it will be suspended.

     * MANDATORY Runs in the existing Transaction. If there is no current existing transaction an exception is thrown.

     * SUPPORTS Use a transaction if it already exists. If it does not then the method runs without a transaction.

     * NOT_SUPPORTS Always runs without a transaction. If one already exists then it is suspended.

     * NEVER Always runs without a transaction. If one already exists then it throws an exception.

     *

     * @param type

     */

    @Transactional// 打开事务。或通过beginTr....  endTr.. 或TxRunnable

    public void saveUser(int type) {

        Util.report("=============saveUser==start===============================");

        if (type == 0) { //不级联情况保存

            this.address.save(); // 保存用户前将用户输入的出生地也保存到数据库

            this.save(); // 保存用户数据

            this.saveManyToManyAssociations("cars"); //保存中间表

        } else if (type == 1) { //假设设置级联car

            this.save(); // 会级联插入car和中间表数据

        }

        Util.report("===============saveUser===end============================");

    }





    public void deleteUser(Long id) {

        Ebean.delete(User.class, id);

    }









    /**

     * *********************other test*********************

     * public void updateUser() {

     * this.update();

     * }

     * <p/>

     * //批量操作

     * public void deleteUser(List<User> users) {

     * Ebean.delete(users);//批量删除

     * Ebean.save(users);//批量保存

     * }

     * <p/>

     * public void deleteUser() {

     * this.delete();

     * }

     * ***************

     */





    //L1 測试 事务级缓存或持久化上下文缓存

    public static User find() {

        Ebean.beginTransaction();

        Car car1 = Car.find.byId(Long.valueOf(7));

        Car car2 = Car.find.byId(Long.valueOf(8));

        User user = User.findById(Long.valueOf(45));

        if (user.cars.get(0).id == 7) { // 查到的car实例属于同一个实例

            Util.report((user.cars.get(0) == car1) + "");

        } else if (user.cars.get(0).id == 8) {

            Util.report((user.cars.get(0) == car2) + "");

        }

        Ebean.endTransaction();

        return user;

    }





    //L2 測试  bean cache and query cache

    public static Address findAddress() {//手动指定使用缓存。同一时候设置为仅仅读。能够在model使用注解指定缓存策略。假设有改动缓存的bean,会自己主动维持缓存

        Address address_ = Ebean.find(Address.class).setUseCache(true).setReadOnly(true).setId(56).findUnique();

        List<Address> addressList = Ebean.find(Address.class).setUseQueryCache(true).setReadOnly(true).findList();

        Util.report(addressList.size() + "");

        return address_;

    }





    // 測试 不用cache 查询10000次 

    public static Car findCar() {

        Car car = null;

        for (int i = 0; i < 100000; i++) {

            Car car_ = Ebean.find(Car.class, 1);

            Util.report((car == car_) + "");

            car = car_;

        }

        return car;

    }









    // 測试 不用cache 查询10000次 

    public static Car findCar2() {

        Car car = null;

        for (int i = 0; i < 10000; i++) { // 仅仅查1次

            Car car_ = Ebean.getReference(Car.class, 1); // getReference 仅仅会载入创建存在id属性的bean。不会查询数据库。当得到这个bean,用id外的其他属性就会引发查询

            Util.report((car == car_) + "");

            car = car_;

        }

        return car;

    }









    //L1 測试  查询10000次 

    public static Address findAddressInL1() { // 仅仅查1次

        //      Address address_ = Ebean.find(Address.class, "56");

        Address address = null;

        Ebean.beginTransaction();

        for (int i = 0; i < 10000; i++) {

            Address address_ = Ebean.find(Address.class, 56);

            Util.report((address == address_) + "");

            address = address_;

        }

        Ebean.endTransaction();

        return address;

    }





    //L2 測试  查询10000次

    public static Address findAddressInL2() {

        Address address = null;

        for (int i = 0; i < 10000; i++) { // 查了数据库

            Address address_ = Ebean.find(Address.class, 56);

//            Address address_ = Ebean.find(Address.class).setUseCache(true).setReadOnly(true).setId(56).findUnique();

            Util.report((address == address_) + "");

            address = address_;

        }

        return address;

    }





    //L2 測试  查询10000次

    public static Address findAddressInL22() {

        Address address = null;

        for (int i = 0; i < 10000; i++) { // 測试查了数据库

            // Address address_ = Ebean.getReference(Address.class,56);

            Address address_ = Ebean.find(Address.class).setUseCache(true).setReadOnly(true).setId(56).findUnique();

            Util.report((address == address_) + "");

            address = address_;

        }

        return address;

    }





    //L2 測试  抓取Address10000次  当第一次查询的时候会查询address,之后会从缓存取

    public static Address findAddressInL222() {

        Address address = null;

        for (int i = 0; i < 10000; i++) { // 測试查了数据库

            User user = User.findById(Long.valueOf(41));

            Address address_ = user.address; // 数据从缓存内得到

            Util.report((address == address_) + (address == null ?

null : address.province));

            address = address_;

        }

        return address;





    }





    /**

     * **

     * Handling External Modification (

     * via stored procedures etc

     * )

     * When you save/delete beans via Ebean.save() and Ebean.delete() etc Ebean will

     * automatically maintain its cache (removing cached beans and cached queries as

     * appropriate). However, you may often find yourself modifying the database outside of

     * Ebean.

     * For example, you could be using other frameworks, your own JDBC code, stored

     * procedures, batch systems etc. When you do so (and you are using Ebean caching) then

     * you can inform Ebean so that it invalidates appropriate parts of its cache.

     */

    public void test() {

        boolean inserts = true;

        boolean updates = true;

        boolean deletes = false;

        // inform Ebean that some rows have been inserted and updated on address table Ebean will maintain the appropriate caches.

        Ebean.externalModification("address", inserts, updates, deletes);

        // clearAll() caches via the ServerCacheManager ...

        ServerCacheManager serverCacheManager = Ebean.getServerCacheManager();

        // Clear all the caches on the default/primary EbeanServer

        serverCacheManager.clearAll();

        // clear both the bean and query cache for Country beans ...

        serverCacheManager.clear(Address.class);

        // Warm the cache of Country beans

        Ebean.runCacheWarming(Address.class);

    }









    @Override

    public String toString() {

        String result = "";

        if (address == null)

            result.concat("address:null");

        else

            result.concat("address:").concat(address.province).concat("-").concat(address.town);

        return result;

    }





}

Ebean Demo的更多相关文章

  1. 通过一个demo了解Redux

    TodoList小demo 效果展示 项目地址 (单向)数据流 数据流是我们的行为与响应的抽象:使用数据流能帮我们明确了行为对应的响应,这和react的状态可预测的思想是不谋而合的. 常见的数据流框架 ...

  2. 很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天说下这些格式,明天做个demo

    有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用. 在看之前你可以扫一扫下面几个二维码先看看效果: 1.二维码生成 网址 (URL) 包含网址的 二维码生成 是大家平时最常接触 ...

  3. 在线浏览PDF之PDF.JS (附demo)

    平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html#skill 下载地址:http://mozilla.gith ...

  4. 【微框架】Maven +SpringBoot 集成 阿里大鱼 短信接口详解与Demo

    Maven+springboot+阿里大于短信验证服务 纠结点:Maven库没有sdk,需要解决 Maven打包找不到相关类,需要解决 ps:最近好久没有写点东西了,项目太紧,今天来一篇 一.本文简介 ...

  5. vue双向数据绑定原理探究(附demo)

    昨天被导师叫去研究了一下vue的双向数据绑定原理...本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊...自己动手写了一个. 传送门 双向绑定的思想 双向数据绑定的思想就是数据层与 ...

  6. Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决

    前提: 1.安装Android Studio(过程略) 2.官网下载OpenCV for Android 网址:http:opencv.org/downloads.html 我下载的是下图的版本 3. ...

  7. iOS之ProtocolBuffer搭建和示例demo

    这次搭建iOS的ProtocolBuffer编译器和把*.proto源文件编译成*.pbobjc.h 和 *.pbobjc.m文件时,碰到不少问题! 搭建pb编译器到时没有什么问题,只是在把*.pro ...

  8. 钉钉开放平台demo调试异常问题解决:hostname in certificate didn't match

    今天研究钉钉的开放平台,结果一个demo整了半天,这帮助系统写的也很难懂.遇到两个问题: 1.首先是执行demo时报unable to find valid certification path to ...

  9. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

随机推荐

  1. (转) 各种好用的插件 Xcode

    时间就是金钱.编码效率的提升意味着更多的收入.可是当我们的开发技巧已经到达一定高度时,如何让开发效率更上一层楼呢?答案就是使用开发工具!在这篇文章中,我会向你介绍一些帮助我提升编码速度和工作效率的工具 ...

  2. bzoj 3781: 小B的询问 分块

    3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 196  Solved: 135[Submit][Status] Descrip ...

  3. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  4. (转)未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService~~导出!解决方案。

    今天刚到公司,打开VS2012准备些个小程序练练手,结果打开C#控制台程序创建时弹出个出错警告,于是呼赶紧跑到百度娘那里问问. 百度一番之后,找到了两篇文章: vs2012建立c++项目为啥会这样? ...

  5. 【LA 5713 】 Qin Shi Huang's National Road System (MST)

    [题意] 秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B ...

  6. http://jinnianshilongnian.iteye.com/blog/1996071

    http://jinnianshilongnian.iteye.com/blog/1996071 http://my.oschina.net/jkcui/blog/388400 http://tian ...

  7. poi 操作excel

    poi操作 创建一个excel关联对象HSSFWorkbook: HSSFWorkbook book = new HSSFWorkbook(); 创建一个sheet: HSSFSheet st = b ...

  8. 6,render的一些概念和可用库

    一,概念解释 什么是渲染?这是高大上的说法,翻译成正常语言,就是把图像缓冲区的数据显示到屏幕的过程,就是渲染. 原理说白了很简单,但实际操作中有太多因素需要考量. OS/硬件提供的加速机制/解码后图像 ...

  9. bzoj1559

    自动机上状压dp,把单词是否存在压成二进制位注意这里面某些单词会包含其他单词,所以某些自动机上有些状态点对应多个二进制位方案只要再顺着有方案的状态搜一遍即可 ..,'a'..'z'] of longi ...

  10. JAVADOC时候乱码-编码 GBK 的不可映射字符

    1,在项目列表中按右键,选择Export(导出),然后在Export(导出)对话框中选择java下的javadoc,提交到下一步.在Javadoc Generation对话框中有两个地方要注意的:ja ...