【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:5.技术简介之Hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。——百度百科
序言
博主在《迷你微信》项目上对Hibernate的使用是通过注解方式配置进行增删改查操作、使用c3p0连接池、使用ehcache缓存。
配置
hibernate.cfg.xml配置文件
主要是有关和MySQL数据库连接的配置、Ehcache、C3P0的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/MiniWechat?useUnicode=true&characterEncoding=UTF-8</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="javax.persistence.validation.mode">none</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- C3P0连接池 -->
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">100</property>
<property name="c3p0.max_size">5</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">2</property>
<property name="c3p0.timeout">90</property>
<property name="c3p0.preferredTestQuery ">SELECT CURRENT_USER</property>
<property name="c3p0.idleConnectionTestPeriod ">18000</property>
<property name="c3p0.maxIdleTime">25000</property>
<property name="c3p0.testConnectionOnCheckout">true</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Ehcache 缓存配置 -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<mapping class="model.User"/>
<mapping class="model.Chatting"/>
<mapping class="model.Group"/>
</session-factory>
</hibernate-configuration>
加载hibernate.cfg.html配置文件并获取Session
public class HibernateSessionFactory {
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
public static SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try{
configuration.configure(configFile);
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(sr);
}catch(Exception e){
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}
public static Session getSession() {
Session session = threadLocal.get();
if (session == null || !session.isOpen()) {
session = (sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
}
对象的注解配置
主要是类的注解配置、成员变量的注解配置、多对多的注解配置
1.在需要在数据库中建表存储的类型需要在类名前添加注解
@Entity
@Table(name="user")
2.在相关成员变量添加注解
@Column(name="user_id",columnDefinition = "char(20) COMMENT '微信号'")
如果是数据库对应的主键需要添加注解:
@Id
如果是自增主键需要添加主键:
@GeneratedValue(strategy = GenerationType.AUTO)
3.多对多关联注解配置
在数据库中我们需要好友关系、聊天群的成员表,但在项目代码中我们并没有定义这样的对象,这是通过多对多的注解配置实现的
例如:
@ManyToMany(targetEntity=User.class)
@JoinTable(name = "user_friends",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "friend_id"))
public List<User> getFriends() {
return friends;
}
public void setFriends(List<User> friends) {
this.friends = friends;
}
增删改查
在项目中为了更好的将有关数据库的操作和业务逻辑分离,同时也有利于BUG和异常的捕获,我们将有关数据库的操作进行了封装,下面的代码只展示了有关Hibernate的增删改查操作的代码,没有展示封装的代码。
具体的增删改查代码
增:
public void add(Object obj){
Session session = HibernateSessionFactory.getSession();
Transaction trans = session.beginTransaction();
session.save(obj);
trans.commit();
session.close();
}
删:
public void delete(Object obj){
Session session = HibernateSessionFactory.getSession();
Transaction trans = session.beginTransaction();
session.delete(o);
trans.commit();
session.close();
}
改:
public void update(Object obj){
Session session = HibernateSessionFactory.getSession();
Transaction trans = session.beginTransaction();
session.update(o);
trans.commit();
session.close();
}
查:
public void query(String paramName, Object paramValue, Class outputClass){
Session session = HibernateSessionFactory.getSession();
Criteria criteria = session.createCriteria(outputClass);
// 使用缓存
criteria.setCacheable(true);
criteria.add(Restrictions.eq(paramName, paramValue));
List list = criteria.list();
session.close();
}
注意:
1.使用了缓存 后面会更加详细的介绍
2.paramValue的类型需要和查询对象定义的类型相匹配,否则会出现类型无法转换的报错
数据库操作的封装
1.将所有的数据库操作放在同一个类中,并声明为静态方法
2.对所有的操作进行异常捕获 避免抛出数据库、Hibernate相关的异常
3.定义枚举类型的ResultCode 返回操作是否成功
4.重要:在项目中 聊天群类型中定义了 聊天成员对象的List,当查询一个聊天群对象时,Hibernate并没有将聊天成员对象的List也查询出来,而是当需要使用的时候再查询,但前面提到的查询方法中调用了session.close(),这时无法再用原来的聊天群对象直接get聊天成员对象的List(Hibernate的延迟加载导致)。所以在封装的数据库操作类中重载了需要使用到延迟加载的相关方法,即:调用相关方法时传入session,在查询等操作时不立即close掉session,待调用者的方法结束时再close。Session是通过sessionFactory.openSession()方法获取,其实通过这种方式获取的ession时Hibernate会自动关闭。
连接池
在项目开始时并没有使用连接池,但出现过一次数据库无法访问的异常。经过查阅资料发现了问题所在:Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该 connection。Hibernate默认的连接池并不知道该connection已经失效,如果这时有 Client请求connection,Hibernate将该失效的Connection提供给Client,将会造成上面的异常。
解决办法:使用C3P0连接池,有关C3P0连接池的配置在hibernate.cfg.xml配置文件中可以查看,需要的jar包可以在Hibernate的安装包可以找到。
其实一开始使用的是C3P0连接池,使用的是Proxool连接池,但使用过程中遇到了连接池销毁连接时的相关报错,而且没有找到很好的解决办法。所以就改用了C3P0连接池
缓存
EhCache是Hibernate的二级缓存技术之一,可以把查询出来的数据存储在内存或者磁盘,节省下次同样查询语句再次查询数据库,大幅减轻数据库压力
1.有关EhCache的配置可以在hibernat.cfg.xml中查看
2.在需要使用缓存的类添加注解
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
3.在数据库的查询操作中设置使用缓存
// 使用缓存
criteria.setCacheable(true);
3.当用Hibernate的方式修改表数据(save,update,delete等等),这时EhCache会自动把缓存中关于此表的所有缓存全部删除掉(这样能达到同步)。但对于数据经常修改的表来说,可能就失去缓存的意义了(不能减轻数据库压力);所以EhCache一般要使用在比较少执行write操作的表(包括update,insert,delete等)[Hibernate的二级缓存也都是这样];
注:本篇来自于数据库调试员:王飞先生
欢迎阅读我的开源项目《迷你微信》服务器与《迷你微信》客户端
【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:5.技术简介之Hibernate的更多相关文章
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:0.概述
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 序言 帖主和队友仿制了一个简单版的微信,其中,队友是用Unity3D做前段,帖主用Java的Mina.Hiberna ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:7.项目介绍之架构(1)
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 前言 <迷你微信>服务器端是使用Java语言,Mina框架编写的,一个良好的架构关系到后期迭代的方便程度 ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:9.观察者模式
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 前言 在一个程序的迭代过程中,复杂度渐渐上升,可能会出现一些跨模块的调用的需求,若是直接得到引用来进行使用,会导致模 ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:8.自定义传输协议
欢迎阅读我的开源项目<迷你微信>服务器)与<迷你微信>客户端 前言 在上一篇中,我们讲到了<迷你微信>服务器)的主体架构,还讲到了如何在现有功能上进行拓展,但是拓展 ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:6.技术简介之Protobuf
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 protocolbuffer(以下简称Protobuf)是google 的一种数据交换的格式,它独立于语言,独立于平 ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统 :1.技术简介之Mina连接
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 Apache MINA(Multipurpose Infrastructure for Network Applic ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:4.技术简介之Spring
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 Spring是一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:3.技术简介之MinaFilter——LoggingFilter (转)
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 LoggingFilter 接下来,使我们对Filter介绍的最后一个——LoggingFilter. 与Proto ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:10.项目介绍之架构(2)
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 前言 前面我们讲到<迷你微信>服务器端的主架构,现在我们来描述一下它的模块详细信息. 网络模块 从上图我 ...
随机推荐
- Leetcode:9. Palindrome Number
这题要求不能使用额外的空间,我也就没做,看了下别人的代码,挺有意义的一道题目,出坏了. 解题思路:从右往左颠倒过来,看看这个值和原来的x值是不是一样,最后还要注意像20这种情况,也是的 public ...
- UT源码116
2)NextDate函数问题 NextDate函数说明一种复杂的关系,即输入变量之间逻辑关系的复杂性 NextDate函数包含三个变量month.day和year,函数的输出为输入日期后一天的日期. ...
- SQL笔记:基础篇
1.BETWEEN AND (查询某个区间的数据) 例如:查询user表中年龄在15-30岁的人 SELECT * FROM user WHERE age between 15 and 30 2.IN ...
- Asp.net Core 启动流程分析
新建的.net core 程序启动本质上是一个控制台应用程序,所以它的入口在Main方法中,所以启动的开始时从Main方法开始. public class Program { public stati ...
- JSONCPP开发环境搭建
环境设置 项目地址 https://github.com/open-source-parsers/jsoncpp.git 操作系统 64位 Fedora 24 安装jsoncpp $ git clon ...
- sass使用参考文档
内容提要 变量 嵌套 占位符选择器 % @mixin 运算 @if @for @each @extend @import 正文 1.变量 //定义变量:声明变量以$开 $baseColor:#ff90 ...
- 猜拳游戏三局两胜------java实现代码
package com.javasm.exerices02; import java.util.ArrayList; import java.util.List; import java.util.R ...
- 上传文件到linux乱码问题
由于linux系统编码一般设置为utf-8,而中文windows下通常默认编码是gbk,因此经常需要将文件名或文件内容编码进行转换,文件名编码转换软件:convmv yum install convm ...
- Travelling (三进制+状压dp)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ ,f= ...
- 微信小程序 —— 微信小程序解析html富文本插件wxParse
下载并把wxParse放到小程序的目录中 github下载地址:https://github.com/icindy/wxParse 一.基本使用方法 1. Copy文件夹wxParse,把wxPars ...