Hibernate mit mehreren Thread (?Locking?)

d0x

Grünschnabel
Hi, ich will mit hibernate folgendes realisieren:
Code:
if( existiert objekt mit ID 1  )
{
        Erhöhe objekt.accessCounter
}
else
{
        Erstellte objekt und setzte accessCounter auf 0
}
Also wenn ein Objekt mit der ID 1 bereits in der Datenbank steht, soll object.accessCounter erhöht werden, andernfalls soll das Objekt angelegt werden.

Das ganze muss aber Threadsafe sein.

Was kann ich am besten dafür verwenden?
Soll ich das Objekt Vor und Nach dem If locken?

Ich hab dazu ein kleines Beispiel mit 3 Klassen geschrieben:

HibernateThread.java
Code:
package priv.example.hibernate;


import java.io.IOException;
import java.sql.SQLException;

public class HibernateThread extends Thread
{
	public static void main(String[] args) throws SQLException, IOException
	{
		// Create a DAO object
		TupleDAO dao = new TupleDAO();

		// Now spawn some threads which try to manipulate the same object
		new HibernateThread(dao, 1).start();
		new HibernateThread(dao, 1).start();
	}

	private TupleDAO	dao;
	private int			id;

	public HibernateThread(TupleDAO dao, int id)
	{
		this.dao = dao;
		this.id = id;
	}

	@Override
	public void run()
	{
		// Try to find a object
		Tuple tuple = (Tuple) dao.find(Tuple.class, this.id);

		if (tuple != null)
		{
			// If it was found, increase the counter
			tuple.setAccessCounter(tuple.getAccessCounter() + 1);
			dao.update(tuple);
		}
		else
		{
			// If it wasn't found, create the obj
			tuple = new Tuple();
			tuple.setId(id);
			dao.save(tuple);
		}
	}
}
Tuple.java
Code:
package priv.example.hibernate;


import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Tuple implements Serializable
{
	private static final long	serialVersionUID	= 2932649664062369505L;

	@Id
	// Application generated Id @GeneratedValue(strategy = GenerationType.AUTO)
	private int					id;

	private int					accessCounter		= 0;

	public Tuple()
	{
	}

	public int getId()
	{
		return id;
	}

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

	public int getAccessCounter()
	{
		return accessCounter;
	}

	public void setAccessCounter(int accessCounter)
	{
		this.accessCounter = accessCounter;
	}

}
TupleDAO.java
Code:
package priv.example.hibernate;


import java.io.Serializable;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

public class TupleDAO
{
	private static SessionFactory	sessionFactory	= null;

	/*
	 * Tuple Dataaccess
	 */

	protected void update(Tuple obj)
	{
		Session session = openSession();

		Transaction tx = session.beginTransaction();
		session.update(obj);
		tx.commit();

		close(session);
	}

	protected void save(Tuple obj)
	{
		Session session = openSession();

		Transaction tx = session.beginTransaction();
		session.save(obj);
		tx.commit();

		close(session);
	}

	protected Object find(Class clazz, Serializable id)
	{
		Object obj = null;

		Session session = openSession();

		Transaction tx = session.beginTransaction();
		obj = session.get(clazz, id);
		tx.commit();

		close(session);

		return obj;
	}

	/*
	 * Hibernate things...
	 */

	public synchronized static Session openSession() throws HibernateException
	{
		if (sessionFactory == null)
		{
			final AnnotationConfiguration cfg = new AnnotationConfiguration();
			cfg.configure();
			sessionFactory = cfg.buildSessionFactory();
		}
		return sessionFactory.openSession();
	}

	public synchronized static void close(Session session)
	{
		if (session != null)
		{
			try
			{
				session.close();
			}
			catch (HibernateException ignored)
			{
				System.err.println("Couldn't close Session - " + ignored);
			}
		}
	}
}


Vielen Dank für eure Hilfe.
 
Hi,

versuch doch mal, die Transactions nicht ins DAO sondern um den Verarbeitungsprozess zu legen.

Spätestens, wenn Du Hibernate mit pessimistic locking betreibst, solltest Du Threadsafe sein.

Sofern Du mit JBoss arbeitest, sollte Dich der Transaktionskoordinator Deines Entitmanagers vor solch Ungemach schützen.

Grüße
gore
 
Zurück