Ebean Demo

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;
    }


}
發佈了45 篇原創文章 · 獲贊 20 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章