Hey guys,
I'm experiencing a weird problem currently, and i dont know how to solve it.
I am using Vaadin and Hibernate for a document analysis webservice. (I am kinda of new to hibernate). I am mostly busy trying to get all the stuff added to the database.
My problem: You can register yourself an account on my web service and log in with it later. That works fine, you can also logout again and create/register new accounts.
Everything works fine while the service is running, but if I stop the server and access the database manually, I'm missing entries in the user database.
I tried to reconstruct how this could happen and found out that Hibernate is adding every(!) user to my users-table UNTIL you login. After this (so after you(a user) logged out again) you can create again new users (via registering), and also login and do stuff. But once the serves is offline: They're missing, only the users that have been registered before the first login are shown!
My User-Class:
Code:
package view.model.database;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 0L;
@Id
@GeneratedValue
private Long userId;
@Column(unique=true)
private String userName;
private String hashedPassword;
@OneToMany(cascade = CascadeType.ALL) //falls nicht cascadeType.ALL exception
private Set<Document> documents = new HashSet<>();
public User(String userName, String hashedPassword){
this.userName = userName;
this.hashedPassword = hashedPassword;
}
//leerer Konstruktor für Hibernate
public User(){ }
//hibernate braucht alle getter und setter
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getHashedPassword() {
return hashedPassword;
}
public void setHashedPassword(String hashedPassword) {
this.hashedPassword = hashedPassword;
}
public Set<Document> getDocuments() {
return Collections.unmodifiableSet(documents);
}
public void addDocument(Document document) {
this.documents.add(document);
}
public void removeDocument(Document document) {
this.documents.remove(document);
}
public void setDocuments(Set<Document> documents) {
this.documents.clear();
this.documents.addAll(documents);
}
}
My UserDAO for adding/updating/removing/getting, I am calling the createUser-Method when a person clicks on "Register":
Code:
package view.model.database;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
public class UserDAO extends DAO {
/**
* Erstellt einen neuen User in der Users-Datenbank
*
* @param user Der zu erstellende User
*/
public void createUser(User user) {
// später noch überprüfen ob User bereits existiert
Session session = getSession();
// speichern des user in der datenbank
session.save(user);
session.flush();
session.evict(user);
if(getTransaction() != null && getTransaction().wasCommitted() == false){
getTransaction().commit();
}
}
/**
* Updated einen User der Datenbank
*/
public void updateUser(User user){
// später noch überprüfen ob User bereits existiert
Session session = getSession();
// updaten des Users in der datenbank
session.merge(user);
// session.saveOrUpdate(user);
session.flush();
session.evict(user);
if(getTransaction() != null && getTransaction().wasCommitted() == false){
getTransaction().commit();
}
}
/**
* Löscht einen User der Datenbank
*/
public void deleteUser(User user){
// später noch überprüfen ob User bereits existiert
Session session = getSession();
// löschen des Users in der datenbank
session.delete(user);
session.flush();
session.evict(user);
if(getTransaction() != null && getTransaction().wasCommitted() == false){
getTransaction().commit();
}
}
/**
* Identifiziere einen User aus der Datenbank anhand seines Nickname
*
* @param username Nickname des Users
* @return Der gesuchte User
*/
public User getUser(String username){
Session session = getSession();
List<User> oneUsers = (List<User>) session.createCriteria(User.class)
.add(Restrictions.eq("userName", username))
.list();
if (oneUsers.size() > 0) {
return oneUsers.get(0);
} else {
return null; // user existiert nicht
}
}
}
The way I am getting my session:
Code:
/**
* Used to get current Hibernate session. Also ensures an open Hibernate
* transaction.
*/
public Session getSession() {
Session currentSession = HibernateUtil.getSessionFactory()
.getCurrentSession();
if(!currentSession.getTransaction().isActive()) {
this.transaction = currentSession.beginTransaction();
}
return currentSession;
}
When a user clicks on logout, I am doing nothing more then (WebsiteFrame is the main Window of my vaadin application):
Code:
public void performLogoutAction() {
WebsiteFrame wf = WebsiteFrame.getDefault();
wf.getMainWindow().getApplication().close();
}
My hibernate-config xml file:
Code:
<?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>
<property name="hibernate.connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="hibernate.connection.url">jdbc:derby:C:\HTML-Ausgabe\database\DocumentDB;create=true</property>
<property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<property name="hibernate.show_sql">true</property>
<mapping class="view.model.database.User"/>
<mapping class="view.model.database.Document"/>
<mapping class="view.model.database.Version"/>
<mapping class="view.model.database.VersionData"/>
</session-factory>
</hibernate-configuration>
Okay, if you need something more, just let me know :) I hope you can understand my classes above and help me with this problem.
If you see something general that I could improve in my code, please let me know, too :)
Thanks a lot for your answers