您的位置:首页 > 编程语言 > Java开发

基于Struts2和hibernate的WebSocket聊天室的实现教程三:Hibernate个人信息管理

2017-11-21 12:15 579 查看
本文将介绍struts2和hibernate在项目中的实际应用

建立pojo类,使用注解配置hibernate映射

在需求分析的时候我们知道需要保存用户的聊天记录,那么怎么保存呢?

我有想过几种方法,比如文件存储,会话存储..但我在实际上操作大都不太可行。于是这次还是简单的把聊天记录储存到mysql数据库中…..

好的,接下来我们要建两个实体类。User和ChatRecord类。

User类用来保存用户信息,一般来说有这么几个属性:

private int id ;//用户id主键
private String name;//用户名
private String avatar;//头像路径
private int sex;//0 for male 1 for female
private Timestamp registerTime;//注册时间
private Timestamp loginTime;//登录时间


但是我们要使用hibernate进行dao层操作,因此在这个实体类中要配置一对多关系映射。毕竟一个用户的聊天记录一般不止一个,与当前用户对应的聊天记录应该是0…*

所以我们还要增加一个属性

private Set<ChatRecord> chatRecords =new HashSet<>();


当然为了方便实例化这个对象,我们还需要设计构造方法

public User() {

}

public User(String name, String avatar, int sex) {
this.name = name;
this.avatar = avatar;
this.sex = sex;
}


使用注解配置实体类的方法也特别简单,这里简单解释一下代码中使用到的注解的作用

@Entity 标注当前类为实体类

@Table 建立与数据库中表的连接

我们一般不在属性前使用注解,这里我们在get方法前添加注解

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

声明数据库表主键,设置数据自增。这里的strategy有多种策略,一般我们使用上面这种

@Column 配置列,保持类型与java类型一致

@Column(name = “registerTime”,columnDefinition = “timestamp default CURRENT_TIMESTAMP”) 对数据库对应列的类型自定义,并且设置默认值。这里是默认使用当前时间。

insertable=false表明在插入数据时无需传入当前注解配置的属性(这里指loginTime)

@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER,mappedBy=”sender”) 配置一对多关系映射,cascadeType设置级联操作,,mappedBy=”sender”注明外键。在ChatRecord类中我们将创建这个sender属性与之对应。

这个时候,User类的代码应该是这样的:

package cn.zipple.entity;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

/**
* Created by zipple on 2017/11/13.
* 用户实体
*/
@Entity
@Table(name = "users")
public class User {
private int id ;
private String name;
private String avatar;//头像路径
private int sex;//0 for male 1 for female
private Timestamp registerTime;
private Timestamp loginTime;
private Set<ChatRecord> chatRecords =new HashSet<>();

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Column(name = "name")
public String getName() {
return name;
}

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

@Column(name = "avatar")
public String getAvatar() {
return avatar;
}

public void setAvatar(String avatar) {
this.avatar = avatar;
}

@Column(name = "gender")
public int getSex() {
return sex;
}

public void setSex(int sex) {
this.sex = sex;
}

@Column(name = "registerTime",columnDefinition = "timestamp default CURRENT_TIMESTAMP")
public Timestamp getRegisterTime() {
return registerTime;
}

public void setRegisterTime(Timestamp registerTime) {
this.registerTime = registerTime;
}

@Column(name = "loginTime",insertable = false)
public Timestamp getLoginTime() {
return loginTime;
}

public void setLoginTime(Timestamp loginTime) {
this.loginTime = loginTime;
}
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER,mappedBy="sender")
public Set<ChatRecord> getChatRecords() {
return chatRecords;
}

public void setChatRecords(Set<ChatRecord> chatRecords) {
this.chatRecords = chatRecords;
}

public User() {

}

public User(String name, String avatar, int sex) {
this.name = name;
this.avatar = avatar;
this.sex = sex;
}
}


同理,在ChatRecord类中我们也这样设计:

@DynamicInsert 动态插入数据

@ManyToOne(cascade = CascadeType.ALL) 多对一映射

@JoinColumn(name=”senderId”) 设置外键(数据库将显示senderId这一列,但是在通过hibernate查询的时候会查询出整个sender对象)

package cn.zipple.entity;

import org.hibernate.annotations.DynamicInsert;

import javax.persistence.*;
import java.sql.Timestamp;

/**
* Created by zipple on 2017/11/13.
* 聊天记录
*/
@Entity
@Table(name = "chatRecord")
@DynamicInsert
public class ChatRecord {
private int id;
private User sender;
private int receiver;//指定id
private String content;
private Timestamp time;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}
//不需要懒加载
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="senderId")
public User getSender() {
return sender;
}

public void setSender(User sender) {
this.sender = sender;
}

@Column(name = "receiverId")
public int getReceiver() {
return receiver;
}

public void setReceiver(int receiver) {
this.receiver = receiver;
}

@Column(name = "content",columnDefinition = "LONGTEXT")
public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

@Column(name = "time",columnDefinition = "timestamp default CURRENT_TIMESTAMP")
public Timestamp getTime() {
return time;
}

public void setTime(Timestamp time) {
this.time = time;
}

public ChatRecord() {
}

public ChatRecord(User sender, int receiver, String content) {
this.sender = sender;
this.receiver = receiver;
this.content = content;
this.time=new Timestamp(System.currentTimeMillis());
}
}


由于我们在第一篇文章中添加hibernate.cfg.xml的时候直接指定了数据库为chatroom,为此我们必须保证mysql中有这个数据库。

所以我们在mysql命令行中使用这句命令创建数据库并且要防止中文乱码,注意事项传送门

CREATE DATABASE IF NOT EXISTS chatroom DEFAULT CHARSET utf8 COLLATE utf8_general_ci;


好的,后面的表什么的就不用我们自己创建了,hibernate在运行时会自动创建。

最后还有一步,我们需要在hibernate.cfg.xml中注册这两个实体类,如下图



编写DAO层方法

使用Hibernate的方法也特别简单,先加载hibernate.cfg.xml这个文件,然后获取SessionFactory获取session,建立事务,进行CRUD,再提交事务即可。详情请点击

我们在util包中建立HibernateUtil类帮助我们获取session

package cn.zipple.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

/**
* Created by zipple on 2017/10/12.
* hibernate 工具类
*/
public class HibernateUtil {
/**
* 连接数据库
* @return 返回session
*/
public static Session getHibernateSession(){
StandardServiceRegistry serviceRegistry=new StandardServiceRegistryBuilder().configure().build();
SessionFactory sessionFactory=new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
return sessionFactory.openSession();
}
}


在dao包里面,添加HibernateDao作为基类,以方便代码复用。

package cn.zipple.dao;

import cn.zipple.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.util.List;

/**
* Created by zipple on 2017/10/12.
* 父类提供基本的公共操作
*/
public class HibernateDao {
/**
* 增加一条记录
* @param object 持久化类
*/
public void save(Object object){
Session session =  HibernateUtil.getHibernateSession();
Transaction tr =session.beginTransaction();
//        session.save(object);
session.saveOrUpdate(object);
tr.commit();
session.close();
}

/**
* 删除记录
* @param object 持久化类
*/
public void del(Object object){
Session session =  HibernateUtil.getHibernateSession();
Transaction tr =session.beginTransaction();
session.delete(object);
tr.commit();
session.close();
}

/**
* 修改对象信息
* @param object 持久化对象
*/
public void upd(Object object){
Session session =  HibernateUtil.getHibernateSession();
Transaction tr =session.beginTransaction();
session.merge(object);//使用merge防止从数据库中查询出来的持久化对象再被查询一次,从而导致异
// 常:illegally attempted to associate a proxy with two open Sessions
//向修改过后的对象 合并
//session.saveOrUpdate(stu);
tr.commit();
session.close();
}

/**
* 获取数据库中所有对象
* @param extra 额外条件--附加条件
* @return 返回对象列表
*/
public List getAllObject(String entityClass,String extra){
Session session = HibernateUtil.getHibernateSession();
String hql = "from "+entityClass+extra;
System.out.println("hql:"+hql);
List studentList = session.createQuery(hql).list();
session.close();
return studentList;
}

/**
* 根据id获取对象
* @param id id
* @return 返回对象
*/
public Object getObjetcById(int id){
Session session = HibernateUtil.getHibernateSession();
Transaction tr =session.beginTransaction();
session.close();
Object obj = session.get(Object.class, id);
tr.commit();
session.close();
return obj;
}
}


同时,我们为这两个实体类建立接口,如下图所示



BaseDaoImpl类实际上只是单纯的继承了HibernateDao这个基类,为什么要建立这个BaseDaoImpl呢,实际上是为了便于对父类进行补充和修改。如下:

package cn.zipple.dao.impl;

import cn.zipple.dao.HibernateDao;

/**
* Created by zipple on 2017/11/13.
* 基类
*/
public class BaseDaoImpl  extends HibernateDao {
}


在ChatRecordDao接口中,没有其他的什么需求需要自定义数据库操作方法,使用常规的CRUD方法即可。于是这个接口这样定义:

package cn.zipple.dao;

/**
* Created by zipple on 2017/11/13.
*/
public interface ChatRecordDao {
}


在impl包中需要实现这个接口,虽然是个空的:

package cn.zipple.dao.impl;

import cn.zipple.dao.ChatRecordDao;

/**
* Created by zipple on 2017/11/18.
*/
public class ChatRecordDaoImpl extends BaseDaoImpl implements ChatRecordDao {
}


但是在UserDao中,我们要补充一个方法,用于用户注册和查询

package cn.zipple.dao;

import cn.zipple.entity.User;

/**
* Created by zipple on 2017/11/13.
*/
public interface UserDao {
/**
* 根据用户名获取用户对象
* @param username 用户名
* @return 返回对象
*/
User getUserByUsername(String username);
}


在impl包中这样实现接口

package cn.zipple.dao.impl;

import cn.zipple.dao.UserDao;
import cn.zipple.entity.User;
import cn.zipple.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.query.Query;

import java.util.List;

/**
* Created by zipple on 2017/11/13.
*/
public class UserDaoImpl extends BaseDaoImpl implements UserDao {
@Override
public User getUserByUsername(String username) {
Session session = HibernateUtil.getHibernateSession();
String hql = "from User where name =:username";//User代表的是User实体类而不是表名
Query query = session.createQuery(hql);
query.setParameter("username",username);
System.out.println("hql:"+hql);
List userList = query.list();
session.close();
if (userList.size()!=0){
return (User) userList.get(0);
}
return null;
}
}


上面的代码中我们使用到了hql,是Hibernate方便我们自定义sql操作而定义的。

下面我们测试HIbernate是否正常工作。

Intellij连接数据库

首先我们检查IDE右侧边栏是否有database一项,如图



有的话就双击

没有的话双击shift打开database界面



选择mysql连接



连接



第一次连接可能没有驱动包,让IDE自动帮你下载即可。

连接成功以后

我们在test包中新建测试类

package cn.zipple.test;

import cn.zipple.dao.impl.BaseDaoImpl;
import cn.zipple.entity.ChatRecord;
import cn.zipple.entity.User;
import cn.zipple.util.Constant;

/**
* Created by zipple on 2017/11/13.
* 测试
*/
public class UserTest {
private BaseDaoImpl baseDao = new BaseDaoImpl();

public static void main(String[] args) {
System.out.println("测试hibernate是否正常工作");
new UserTest().testAdd();
}

private void testAdd(){
User user1 = new User("邹博","01.jpg", Constant.MALE);
User user2 = new User("李欣雨","02.jpg", Constant.FEMALE);
System.out.println("储存用户1");
baseDao.save(user1);//先保存没有维护关系的那一方
System.out.println("储存用户2");
baseDao.save(user2);
ChatRecord temp = new ChatRecord(user1,user2.getId(),"这是第一条测试信息");
System.out.println("储存聊天信息");
baseDao.save(temp);
}
}


测试成功运行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐