一、Gemfire相关
Gemfire是内存数据库,即它依托于内存实现数据的操作,但是对于单机来说,内存不是很大,因此Gemfire也支持集群。Gemfire利用集群机器的内存,然后将其划分成一个个Region,Region相当于关系型数据库中的表,其内部存储结构为key/value的形式,换句话说,存储的数据类似于一个大map。Gemfire支持OQL(Object Query Language),可以编写OQL语句查询数据。
二、Demo设计流程
首先通过JDBC从sqlserver中读出数据;然后将数据组按照每行的ID作为键,每行数据作为对象实例放入到map集合;然后利用Gemfire提供的接口将该map存入Gemfire,之后写OQL语句查询数据。
三、设计实现
1、JDBC查询sql读取数据并转化成Map<ID,Obj>的形式
package gemfire.getdata;
import gemfire.model.DynamicNews;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class GetDataFromSqlServer {
private final String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private final String url ="jdbc:sqlserver://10.1.5.106:1433; DatabaseName=JYDB";
private final String username ="READ";
private final String password ="READ";
/**
* 根据URL,username,Password获取数据库连接
* @author shihj
* @return
*/
private Connection getConnection(){
Connection dbConn = null;
try{
Class.forName(driverName);
dbConn = DriverManager.getConnection(url, username, password);
}catch(Exception e){
e.printStackTrace();
}
return dbConn;
}
/**
* 根据sql查询结果集
* @author shihj
* @param sql
* @return
* @throws
* @throws IllegalArgumentException
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Map<Long,DynamicNews> query(String sql){
Map<Long,DynamicNews> ret = new HashMap();
try(Statement st = getConnection().createStatement();ResultSet rs = st.executeQuery(sql);) {
ResultSetMetaData md = rs.getMetaData(); //得到结果集(rs)的结构信息,比如字段数、字段名等
int columnCount = md.getColumnCount(); //返回此 ResultSet 对象中的列数
//业务对象的属性数组
Field[] fields = DynamicNews.class.getDeclaredFields();
while(rs.next()){//对每一条记录进行操作
Object obj = DynamicNews.class.newInstance();//构造业务对象实体
//将每一个字段取出进行赋值
for(int i = 1;i<=columnCount;i++){
Object value = rs.getObject(i);
//寻找该列对应的对象属性
for(int j=0;j<fields.length;j++){
Field f = fields[j];
//如果匹配进行赋值
if(f.getName().equalsIgnoreCase(md.getColumnName(i))){
boolean flag = f.isAccessible();
f.setAccessible(true);
switch(f.getGenericType().toString()){
case "class java.lang.Integer":
f.set(obj, value == null ? value : Integer.parseInt(value.toString().trim()));
break;
case "class java.lang.Long":
f.set(obj, value == null ? value : Long.parseLong(value.toString().trim()));
break;
default:
f.set(obj, value);
break;
}
f.setAccessible(flag);
}
}
}
ret.put(((DynamicNews)obj).getID(),(DynamicNews)obj);
}
} catch (SQLException | IllegalAccessException|InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ret;
}
public static void main(String[] args) throws Exception{
System.out.println(new GetDataFromSqlServer().query("Select top 2 * from NI_DynamicNews"));
}
}
2、sqlserver表映射实体类
package gemfire.model;
import java.io.Serializable;
import java.util.Date;
public class DynamicNews implements Serializable{
private static final long serialVersionUID = 8421034353120794834L;
private Long ID;
private Date InfoPublDate;
private String InfoTitle;
private Integer Category;
private Integer NewsType;
private Integer MediaCode;
private String Media;
private String InfoURL;
// private Text Content;
// private Byte[] PictureContent;
private Integer PictureType;
private String PictureURL;
private Date UpdateTime;
private Long JSID;
private Integer Flag;
public Long getID() {
return ID;
}
public void setID(Long iD) {
ID = iD;
}
public Date getInfoPublDate() {
return InfoPublDate;
}
public void setInfoPublDate(Date infoPublDate) {
InfoPublDate = infoPublDate;
}
public String getInfoTitle() {
return InfoTitle;
}
public void setInfoTitle(String infoTitle) {
InfoTitle = infoTitle;
}
public Integer getCategory() {
return Category;
}
public void setCategory(Integer category) {
Category = category;
}
public Integer getNewsType() {
return NewsType;
}
public void setNewsType(Integer newsType) {
NewsType = newsType;
}
public Integer getMediaCode() {
return MediaCode;
}
public void setMediaCode(Integer mediaCode) {
MediaCode = mediaCode;
}
public String getMedia() {
return Media;
}
public void setMedia(String media) {
Media = media;
}
public String getInfoURL() {
return InfoURL;
}
public void setInfoURL(String infoURL) {
InfoURL = infoURL;
}
public Integer getPictureType() {
return PictureType;
}
public void setPictureType(Integer pictureType) {
PictureType = pictureType;
}
public String getPictureURL() {
return PictureURL;
}
public void setPictureURL(String pictureURL) {
PictureURL = pictureURL;
}
public Date getUpdateTime() {
return UpdateTime;
}
public void setUpdateTime(Date updateTime) {
UpdateTime = updateTime;
}
public Long getJSID() {
return JSID;
}
public void setJSID(Long jSID) {
JSID = jSID;
}
public Integer getFlag() {
return Flag;
}
public void setFlag(Integer flag) {
Flag = flag;
}
public String toString(){
return "id=" + this.ID+
";InfoPublDate="+this.InfoPublDate+
";InfoTitle="+this.InfoTitle+
";Category="+this.Category+
";NewsType="+this.NewsType+
";MediaCode="+this.MediaCode+
";Media="+this.Media+
";InfoURL="+this.InfoURL+
";PictureType="+this.PictureType+
";PictureURL="+this.PictureURL+
";UpdateTime="+this.UpdateTime+
";JSID="+this.JSID+
";Flag="+this.Flag;
}
}
注意:因为后面需要将该实体类放到Gemfire中,以便能够在查询时能将结果再变成实体类对象,所以,实体类的实现需要实现序列化接口,否则,在查询时会报错。
3、构造Gemfire服务
首先,需要通过配置文件配置Gemfire集群的位置,命名为cache.xml,配置文件如下:
<?xml version="1.0"?>
<!DOCTYPE client-cache PUBLIC
"-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
"http://www.gemstone.com/dtd/cache6_5.dtd">
<client-cache>
<pool name="client" subscription-enabled="true">
<locator host="10.139.101.113" port="1527"/>
<locator host="10.139.106.159" port="1527"/>
</pool>
</client-cache>
然后,读取该配置文件,建立CacheServer,代码如下:
package gemfire.option;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
public class CacheServer {
private volatile static ClientCache singleton = null;
private CacheServer (){
}
public static ClientCache getCache(){
if (singleton == null) {
synchronized (CacheServer.class) {
if (singleton == null) {
singleton = new ClientCacheFactory() .set("name", "client")
.set("cache-xml-file", "cache.xml").create();
}
}
}
return singleton;
}
@Override
protected void finalize() throws Throwable
{
singleton.close();
singleton = null;
super.finalize();
}
}
第三步,可以依托写好的CacheServer封装一些操作,比如查询,或者写入操作,因Gemfire可以定义很多个Region,所以,可以将Region写入配置文件,然后读取配置文件,再通过regionName获得相应的region操作,本例中region配置如下:
<?xml version="1.0"?>
<!DOCTYPE client-cache PUBLIC
"-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
"http://www.gemstone.com/dtd/cache6_5.dtd">
<client-cache>
<region-attributes id="clientAttributes" pool-name="client"
refid="CACHING_PROXY" />
<region name="TEST_REGION">
<region-attributes refid="clientAttributes" />
</region>
</client-cache>
第四步,创建GemfireOption类:
package gemfire.option;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.query.Query;
import com.gemstone.gemfire.cache.query.QueryService;
public class GemfireOption{
//获取一个cache操作,类似于操作数据库的句柄
ClientCache cache = CacheServer.getCache();
//读取region的配置
public GemfireOption() throws FileNotFoundException{
String path = System.getProperty("user.dir")
+ java.io.File.separator + "bin"+"\\"+"Rengion.xml";
System.out.println(path);
File f = new File(path);
InputStream in = new FileInputStream(f);
this.cache.loadCacheXml(in);
}
//存值
public void RengionPutAll(String rengionName, Map<?, ?> map){
cache.getRegion(rengionName).putAll(map);
}
//查询数据
public Object query(String queryStr){
Object obj = null;
try{
QueryService queryService = cache.getQueryService();
Query query = queryService.newQuery(queryStr);
obj = query.execute();
}catch (Exception e){
e.printStackTrace();
}
return obj;
}
}
4、测试类
package gemfire;
import java.io.FileNotFoundException;
import gemfire.getdata.GetDataFromSqlServer;
import gemfire.option.GemfireOption;
public class App {
public static void main(String[] args) throws FileNotFoundException {
GemfireOption co = new GemfireOption();
co.RengionPutAll("TEST_REGION", new GetDataFromSqlServer().query("SELECT TOP 10000 * FROM NI_DynamicNews"));
System.out.println(co.query("SELECT * FROM /TEST_REGION d WHERE d.JSID ="+Long.parseLong("467322321052".trim())+"l").toString());
System.out.println(Long.parseLong("467322321052".trim()));
}
}
四、运行测试
1、首先如果region不存在则需要在集群先创建
上图所示创建region成功。
2、将数据实体类打包上传至gemfire
3、以上步骤完成之后运行App.java并查看执行结果
五、总结
Gemfire算是一款优秀的内存数据库,查询时不仅仅是取出内存中的值,而且可以按照内存中的列来进行数据查询,从上面的查询语句可以看出,操作完全跟数据库中的操作是相同的,这也是它的特点之一。由于是第一次接触Gemfire,研究的也不是很深入,做个记录方便以后查阅。