Jedis應用之JOhm


Jedis是Redis的一種Java客戶端,是官方推薦使用的,項目中需要使用Redis作為緩存,提高前台查詢效率。

JOhm是Java Object-Hash Mapping的縮寫,是Ohm的一種實現,應用到Jedis中優勢主要體現在不需要更改現有Javabean的結構,

添加簡單的annotation即可實現如ORM框架一樣的對象存取。

參考資料:

GitHub主頁:https://github.com/xetorthio/johm

Google Project:http://code.google.com/p/johm/

IBM DeveloperWorks:http://www.ibm.com/developerworks/cn/java/j-javadev2-22/(Java 開發 2.0: 現實世界中的 Redis)

在使用的過程中,會出現很多個Java.lang.NoSuchMethodException,主要是Jedis版本和JOhm的版本不兼容導致的,我使用的是Jedis-2.1和JOhm0.5,無奈,

只能取來JOhm的源碼進行修改重新編譯打包,通過測試用例測試暫時沒有發現其它問題。

示例如下,Javabean:

package test.java.redis.clients.johm.models;

import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.johm.Array;
import redis.clients.johm.Attribute;
import redis.clients.johm.CollectionList;
import redis.clients.johm.CollectionMap;
import redis.clients.johm.CollectionSet;
import redis.clients.johm.CollectionSortedSet;
import redis.clients.johm.Id;
import redis.clients.johm.Indexed;
import redis.clients.johm.Model;
import redis.clients.johm.Reference;

@Model
public class User
{
    @Id
    private Long id;

    @Attribute
    @Indexed
    private String name;

    @Attribute
    private String room;

    @Attribute
    @Indexed
    private int age;

    @Attribute
    private float salary;

    @Attribute
    private char initial;

    @Reference
    @Indexed
    private Country country;

    @CollectionList(of = Item.class)
    @Indexed
    private List<Item> likes;

    @CollectionSet(of = Item.class)
    @Indexed
    private Set<Item> purchases;

    @CollectionMap(key = Integer.class, value = Item.class)
    @Indexed
    private Map<Integer, Item> favoritePurchases;

    @CollectionSortedSet(of = Item.class, by = "price")
    @Indexed
    private Set<Item> orderedPurchases;

    @Array(of = Item.class, length = 3)
    @Indexed
    private Item[] threeLatestPurchases;

    public Long getId()
    {
        return id;
    }

    public List<Item> getLikes()
    {
        return likes;
    }

    public Set<Item> getPurchases()
    {
        return purchases;
    }

    public Set<Item> getOrderedPurchases()
    {
        return orderedPurchases;
    }

    public Map<Integer, Item> getFavoritePurchases()
    {
        return favoritePurchases;
    }

    public void setThreeLatestPurchases(Item[] threeLatestPurchases)
    {
        this.threeLatestPurchases = threeLatestPurchases;
    }

    public Item[] getThreeLatestPurchases()
    {
        return threeLatestPurchases;
    }

    public Country getCountry()
    {
        return country;
    }

    public void setCountry(Country country)
    {
        this.country = country;
    }

    public String getRoom()
    {
        return room;
    }

    public void setRoom(String room)
    {
        this.room = room;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    public float getSalary()
    {
        return salary;
    }

    public void setSalary(float salary)
    {
        this.salary = salary;
    }

    public char getInitial()
    {
        return initial;
    }

    public void setInitial(char initial)
    {
        this.initial = initial;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((country == null) ? 0 : country.hashCode());
        result = prime * result + ((favoritePurchases == null) ? 0 : favoritePurchases.hashCode());
        result = prime * result + initial;
        result = prime * result + ((likes == null) ? 0 : likes.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((purchases == null) ? 0 : purchases.hashCode());
        result = prime * result + ((room == null) ? 0 : room.hashCode());
        result = prime * result + Float.floatToIntBits(salary);
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj == null)
        {
            return false;
        }
        if (this.getClass() != obj.getClass())
        {
            return false;
        }
        User other = (User) obj;
        if (age != other.age)
        {
            return false;
        }
        if (country == null)
        {
            if (other.country != null)
            {
                return false;
            }
        }
        else if (!country.equals(other.country))
        {
            return false;
        }
        if (favoritePurchases == null)
        {
            if (other.favoritePurchases != null)
            {
                return false;
            }
        }
        else if (!favoritePurchases.equals(other.favoritePurchases))
        {
            return false;
        }
        if (initial != other.initial)
        {
            return false;
        }
        if (likes == null)
        {
            if (other.likes != null)
            {
                return false;
            }
        }
        else if (!likes.equals(other.likes))
        {
            return false;
        }
        if (name == null)
        {
            if (other.name != null)
            {
                return false;
            }
        }
        else if (!name.equals(other.name))
        {
            return false;
        }
        if (purchases == null)
        {
            if (other.purchases != null)
            {
                return false;
            }
        }
        else if (!purchases.equals(other.purchases))
        {
            return false;
        }
        if (room == null)
        {
            if (other.room != null)
            {
                return false;
            }
        }
        else if (!room.equals(other.room))
        {
            return false;
        }
        if (Float.floatToIntBits(salary) != Float.floatToIntBits(other.salary))
        {
            return false;
        }
        return true;
    }
}

單元測試類父類,主要是初始化Jedis連接池:

package test.java.redis.clients.johm;

import org.junit.Assert;
import org.junit.Before;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import redis.clients.johm.JOhm;

public class JOhmTestBase extends Assert
{
    protected JedisPool jedisPool;
    protected volatile static boolean benchmarkMode = true;

    @Before
    public void startUp()
    {
        this.startJedisEngine();
    }

    protected void startJedisEngine()
    {
        // 參數配置
        JedisPoolConfig config = new JedisPoolConfig();

        // 設置參數
        config.setMaxActive(10000);
        config.setMaxIdle(10000);
        config.setMaxWait(10000);

        if (benchmarkMode)
        {
            jedisPool = new JedisPool(config, "localhost", Protocol.DEFAULT_PORT, 50000);
        }
        else
        {
            jedisPool = new JedisPool(config, "localhost");
        }
        JOhm.setPool(jedisPool);
        this.purgeRedis();
    }

    protected void purgeRedis()
    {
        Jedis jedis = jedisPool.getResource();
        jedis.flushAll();
        jedisPool.returnResource(jedis);
    }
}


測試類,查詢測試 SearchTest

package test.java.redis.clients.johm;

import java.util.List;

import org.junit.Test;

import redis.clients.johm.InvalidFieldException;
import redis.clients.johm.JOhm;
import test.java.redis.clients.johm.models.Country;
import test.java.redis.clients.johm.models.Item;
import test.java.redis.clients.johm.models.User;

public class SearchTest extends JOhmTestBase
{
    /**
     * attributeName參數如果為空的話,拋出InvalidFieldException異常
     */
    @Test(expected = InvalidFieldException.class)
    public void cannotSearchOnNullField()
    {
        User user1 = new User();
        user1.setName("model1");
        user1.setRoom("tworoom");
        user1.setAge(88);
        JOhm.save(user1);

        List<User> users = JOhm.find(User.class, "name", "model1");

        for (User user : users)
        {
            System.out.println(user.getRoom());
        }
    }

    /**
     * attributeValue參數如果為空的話,拋出InvalidFieldException異常
     */
    @Test(expected = InvalidFieldException.class)
    public void cannotSearchWithNullValue()
    {
        User user1 = new User();
        user1.setName("model1");
        user1.setRoom("tworoom");
        user1.setAge(88);
        JOhm.save(user1);

        JOhm.find(User.class, "age", null);
    }

    /**
     * attributeName不為索引字段時不能被查找
     */
    @Test(expected = InvalidFieldException.class)
    public void cannotSearchWithOnNotIndexedFields()
    {
        User user1 = new User();
        user1.setName("model1");
        user1.setRoom("tworoom");
        user1.setAge(88);
        JOhm.save(user1);

        JOhm.find(User.class, "salary", 1000);
    }

    @Test
    public void checkModelSearch()
    {
        User user1 = new User();
        user1.setName("model1");
        user1.setRoom("tworoom");
        user1.setAge(88);
        user1.setSalary(9999.99f);
        user1.setInitial('m');
        JOhm.save(user1);
        Long id1 = user1.getId();

        User user2 = new User();
        user2.setName("zmodel2");
        user2.setRoom("threeroom");
        user2.setAge(8);
        user2.setInitial('z');
        user2 = JOhm.save(user2);
        Long id2 = user2.getId();

        assertNotNull(JOhm.get(User.class, id1));
        assertNotNull(JOhm.get(User.class, id2));

        List<User> users = JOhm.find(User.class, "age", 88);
        assertEquals(1, users.size());
        User user1Found = users.get(0);
        assertEquals(user1Found.getAge(), user1.getAge());
        assertEquals(user1Found.getName(), user1.getName());
        assertNotNull(user1Found.getRoom());
        assertEquals(user1Found.getSalary(), user1.getSalary(), 0D);
        assertEquals(user1Found.getInitial(), user1.getInitial());

        users = JOhm.find(User.class, "age", 8);
        assertEquals(1, users.size());
        User user2Found = users.get(0);
        assertEquals(user2Found.getAge(), user2.getAge());
        assertEquals(user2Found.getName(), user2.getName());
        assertNotNull(user2Found.getRoom());
        assertEquals(user2Found.getSalary(), user2.getSalary(), 0D);
        assertEquals(user2Found.getInitial(), user2.getInitial());

        users = JOhm.find(User.class, "name", "model1");
        assertEquals(1, users.size());
        User user3Found = users.get(0);
        assertEquals(user3Found.getAge(), user1.getAge());
        assertEquals(user3Found.getName(), user1.getName());
        assertNotNull(user3Found.getRoom());
        assertEquals(user3Found.getSalary(), user1.getSalary(), 0D);
        assertEquals(user3Found.getInitial(), user1.getInitial());

        users = JOhm.find(User.class, "name", "zmodel2");
        assertEquals(1, users.size());
        User user4Found = users.get(0);
        assertEquals(user4Found.getAge(), user2.getAge());
        assertEquals(user4Found.getName(), user2.getName());
        assertNotNull(user4Found.getRoom());
        assertEquals(user4Found.getSalary(), user2.getSalary(), 0D);
        assertEquals(user4Found.getInitial(), user2.getInitial());
    }

    @Test
    public void canSearchOnLists()
    {
        Item item = new Item();
        item.setName("bar");
        JOhm.save(item);

        User user1 = new User();
        user1.setName("foo");
        JOhm.save(user1);
        user1.getLikes().add(item);

        User user2 = new User();
        user2.setName("car");
        JOhm.save(user2);
        user2.getLikes().add(item);

        List<User> users = JOhm.find(User.class, "likes", item.getId());

        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user2.getId(), users.get(1).getId());
    }

    @Test
    public void canSearchOnArrays()
    {
        Item item0 = new Item();
        item0.setName("Foo0");
        JOhm.save(item0);

        Item item1 = new Item();
        item1.setName("Foo1");
        JOhm.save(item1);

        Item item2 = new Item();
        item2.setName("Foo2");
        JOhm.save(item2);

        User user1 = new User();
        user1.setName("foo");
        user1.setThreeLatestPurchases(new Item[] { item0, item1, item2 });
        JOhm.save(user1);

        User user2 = new User();
        user2.setName("car");
        JOhm.save(user2);

        List<User> users = JOhm.find(User.class, "threeLatestPurchases", item0.getId());
        assertEquals(1, users.size());
        assertEquals(user1.getId(), users.get(0).getId());

        User user3 = new User();
        user3.setName("foo");
        user3.setThreeLatestPurchases(new Item[] { item0, item1, item2 });
        JOhm.save(user3);

        users = JOhm.find(User.class, "threeLatestPurchases", item0.getId());
        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user3.getId(), users.get(1).getId());
    }

    @Test
    public void canSearchOnSets()
    {
        Item item = new Item();
        item.setName("bar");
        JOhm.save(item);

        User user1 = new User();
        user1.setName("foo");
        JOhm.save(user1);
        user1.getPurchases().add(item);

        User user2 = new User();
        user2.setName("car");
        JOhm.save(user2);
        user2.getPurchases().add(item);

        List<User> users = JOhm.find(User.class, "purchases", item.getId());

        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user2.getId(), users.get(1).getId());
    }

    @Test
    public void canSearchOnSortedSets()
    {
        Item item = new Item();
        item.setName("bar");
        JOhm.save(item);

        User user1 = new User();
        user1.setName("foo");
        JOhm.save(user1);
        user1.getOrderedPurchases().add(item);

        User user2 = new User();
        user2.setName("car");
        JOhm.save(user2);
        user2.getOrderedPurchases().add(item);

        List<User> users = JOhm.find(User.class, "orderedPurchases", item.getId());

        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user2.getId(), users.get(1).getId());
    }

    @Test
    public void canSearchOnMaps()
    {
        Item item = new Item();
        item.setName("bar");
        JOhm.save(item);

        User user1 = new User();
        user1.setName("foo");
        JOhm.save(user1);
        user1.getFavoritePurchases().put(1, item);

        User user2 = new User();
        user2.setName("car");
        JOhm.save(user2);
        user2.getFavoritePurchases().put(1, item);

        List<User> users = JOhm.find(User.class, "favoritePurchases", item.getId());

        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user2.getId(), users.get(1).getId());
    }

    @Test
    public void canSearchOnReferences()
    {
        Country somewhere = new Country();
        somewhere.setName("somewhere");
        JOhm.save(somewhere);

        User user1 = new User();
        user1.setCountry(somewhere);
        JOhm.save(user1);

        User user2 = new User();
        user2.setCountry(somewhere);
        JOhm.save(user2);

        List<User> users = JOhm.find(User.class, "country", somewhere.getId());

        assertEquals(2, users.size());
        assertNotSame(user1.getId(), users.get(0).getId());
        assertNotSame(user2.getId(), users.get(1).getId());
    }

    @Test
    public void cannotSearchAfterDeletingIndexes()
    {
        User user = new User();
        user.setAge(88);
        JOhm.save(user);

        user.setAge(77); // younger
        JOhm.save(user);

        user.setAge(66); // younger still
        JOhm.save(user);

        Long id = user.getId();

        assertNotNull(JOhm.get(User.class, id));

        List<User> users = JOhm.find(User.class, "age", 88);
        assertEquals(0, users.size()); // index already updated
        users = JOhm.find(User.class, "age", 77);
        assertEquals(0, users.size()); // index already updated
        users = JOhm.find(User.class, "age", 66);
        assertEquals(1, users.size());

        JOhm.delete(User.class, id);

        users = JOhm.find(User.class, "age", 88);
        assertEquals(0, users.size());
        users = JOhm.find(User.class, "age", 77);
        assertEquals(0, users.size());
        users = JOhm.find(User.class, "age", 66);
        assertEquals(0, users.size());

        assertNull(JOhm.get(User.class, id));
    }
}

 

其它在應用中發現的問題和心得,今后陸續的更新上來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM