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. html多行注释方法

    Html单行:<!-- -->多行:<!-- -->javascript单行://多行:/* */Vbscript单行:'多行:'ASP <% %>中: 单行:'  ...

  2. Rewrite Path in Asp.Net MVC Project

    // Change the current path so that the Routing handler can correctly interpret // the request, then ...

  3. PPT2010小技巧 教你如何快捷抠图

    相信不少人在做PPT时,都有想插入个漂亮个性图案的想法,但是往往手头上的图片都不太令人满意,需要“裁剪”一下才能达不到自己想要的效果.这时大部分人可能会PS,但是相比起今天要分享给大家的方法,步骤就显 ...

  4. 限制sqlserver最大内存后无法连接-EXEC sp_configure max server memory

    在sql server 中设置了过小的 "max server memory"最大内存后,sqlserver可启动,但是无法连接. 网络上流行的"sqlserver 内存 ...

  5. What is machine learning?

    What is machine learning? One area of technology that is helping improve the services that we use on ...

  6. Mozilla公布WebVR API标准草案

    随着信息技术的迅速发展,虚拟现实(Virtual Reality,VR)技术在近些年不断完善,其应用范围也变得十分广泛.为了搭建逼真的虚拟场景,VR技术一般都需要用到大量精美的图像和复杂的动作.因此, ...

  7. TortoiseSVN下载,安装,配置,常用操作 svn教程

    一. 首先在百度搜索并下载 TortoiseSVN 推荐从官网下载,软件分为32位和64位版本,下载时请根据自己的系统位数进行下载:

  8. ANDROID_MARS学习笔记_S05_002_给传感器注册listener

    1 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); se ...

  9. 使用Spring AOP预处理Controller的参数

    实际编程中,可能会有这样一种情况,前台传过来的参数,我们需要一定的处理才能使用,比如有这样一个Controller @Controller public class MatchOddsControll ...

  10. 17.1.1.2 Setting the Replication Slave Configuration

    17.1.1.2 Setting the Replication Slave Configuration 在一个复制slave, 你必须创建一个唯一的server ID,如果这个没有做,slave设置 ...