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)); } }
其它在應用中發現的問題和心得,今后陸續的更新上來。