Hibernate - Performance

y0dA

Erfahrenes Mitglied
Hi!
Ich habe eine Liste von Objekten über welche ich iteriere und für jedes Objekt in der Liste muss ich zumindest 2 Datenbankabfragen absetzen (max 3 Statements). Kann ich hierbei irgendwie performen, denn im Moment dauert das Ganze sehr lange - nach jedem Stmt kommt ein commit etc. Gibt es Prepared Stmts in Hibernate, wie kann ich jene benützen?

Hier mal die Methode die min. 2 mal pro Objekt benutzt wird:
Code:
public static List<FeatureModel> getNearestNeighbour4Point(final double[] point, final int nnNumRes,
			final String unit, final int featureType, final int withinDistance, final int srid) {	
		StringBuffer point2 = new StringBuffer();
		point2.append(" SDO_GEOMETRY( ");
		point2.append(FeatureDB.POINT_GTYPE);
		point2.append(", ");
		point2.append(srid);
		point2.append(", ");
		point2.append("SDO_POINT_TYPE( ");
		point2.append(point[0]);
		point2.append(", ");
		point2.append(point[1]);
		point2.append(", null), null, null)");		
		
		StringBuffer sb = new StringBuffer();
		sb.append(" SELECT {feature.*} ");
		sb.append(" FROM feature {feature} ");
		sb.append(" WHERE SDO_NN ( ");
		sb.append(" feature.f_geom, ");
		sb.append(point2.toString());
		sb.append(", '");
		sb.append(" SDO_NUM_RES = ");
		sb.append(nnNumRes);
		sb.append(" ");
		sb.append(unit);
		sb.append("', 1) = 'TRUE' AND SDO_WITHIN_DISTANCE( feature.f_geom, ");
		sb.append(point2.toString());
		sb.append(", ' DISTANCE = ");
		sb.append(withinDistance);
		sb.append(" ");
		sb.append(unit);
		sb.append("') = 'TRUE' AND f_ft_id = ");
		sb.append(featureType);

		Session session = HibernateUtil.getCurrentSession();
		Transaction tx = null;
		List<FeatureModel> list = null;
		
		try {
			tx = session.beginTransaction();	
			SQLQuery q = session.createSQLQuery(sb.toString());
			q.addEntity("feature", FeatureModel.class);
			list = q.list();

			/* commit and close session */
			tx.commit();	
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			session = null;
			tx = null;
		}
		return list;
	}
 
Gibt's einen Grund dafür, dass du mit SQL arbeitest und das Hibernate so quasi "umgehst"? Ich denke HQL könnte da um einiges performanter sein...

Ansonsten halt noch die Frage ob der SecondLevelCache schon an ist ... teilweise kann man auch Performance rausholen, indem man Objekte lazy setzt (so dass sie nur bei Bedarf aus der Datenbank nachgeladen werden und nicht immer komplett)

Zum Thema PreparedStatement: Klar gibt's sowas, aber kenn ich auch nur mit HQL bisher... möglich, dass die in SQL-Querys genauso gehen. Beispiel:
Code:
String queryString = " SELECT device FROM MyDevice device WHERE device.address = :device_address AND device.id = :id";
Query query = hibernateSession.createQuery(queryString);
query.setInteger("device_address", 123);
query.setString("id", "irgendeineID");
MyDevice myDevice = (MyDevice) query.uniqueResult();
 
Zuletzt bearbeitet:
Mein Problem ist dass ich hier nichts aus einer Tabelle laden möchte sondern eine Oracle XE Function benutzen möchte SDO_NN um den nearest neighbour zu ermitteln - nun stellt sich für mich die Frage, kann ich das auch mit HQL oder muss ich, wie oben, SQL benutzen?
 
Ok, so genau hatte ich mir den Code dann doch nicht durchgelesen ... kann dann leider auch nicht weiterhelfen. Funktionen bieten ja die meisten Datenbanken an, von daher würde ich sagen: Klar geht's "irgendwie" mit HQL, man muss nur ein geeignetes Mapping finden, aber wie das geht ... hier gibt's aber einige Hibernate-Profis, die schauen hier bestimmt bald rein, wenn du Glück hast :)
 
Warum machst du für jede Anfrage eine Transaktion? das sind doch nur selects, oder? Das readonly flag bei Oracle bringt ungemein etwas, da die sich dann den tablelock spart...

Gruß
Ollie
 
Warum machst du für jede Anfrage eine Transaktion? das sind doch nur selects, oder? Das readonly flag bei Oracle bringt ungemein etwas, da die sich dann den tablelock spart...

Gruß
Ollie

Da bin ich grad dabei, also dass alle stmts ausgeführt werden und dann erst ein einmaliges commit - jedoch was meinst du mit dem "readOnly flag"?
 
Code:
Connection.setReadonly(true);
Müsstest du wahrscheinlich in der HibernateUtils Klasse irgendwo möglich machen. Ich halte plain Hibernate mit diesen komischen Helperklassen eh für etwas suboptimal, weil die Trennung von Connection und Transaktionen nicht wirklich gelungen ist, meiner Meinung nach. FlushMode.NEVER bewirkt wohl ähnliches...

Gruß
Ollie
 
Im Moment sieht meine Hibernate Helper Klasse so aus, wie sollte ich die nun umgestalten für readonly?
Code:
public class HibernateUtil {

	//------------------------------------------------------------------------------------------------------------------
    // FIELDS
    //------------------------------------------------------------------------------------------------------------------

	/**
	 * hibernate session factory object
	 * singleton
	 */
	private static SessionFactory sf = null;
	
	/** hibernate database configuration file */
	private static final String HIBERNATE_CONFIG_FILE = "hibernate.cfg.xml";
	
	/** logger */
	private static final Logger LOGGER = Logger.getLogger(HibernateUtil.class.getName());
	//------------------------------------------------------------------------------------------------------------------
    // GETTER/SETTER
    //------------------------------------------------------------------------------------------------------------------

	/**
	 * getter method
	 * 
	 * initialize singleton <code>sf</code>
	 * 
	 * @return hibernate session factory
	 */
	private synchronized static SessionFactory getSessionFactory() {
		if (HibernateUtil.sf == null) {
			 /* log info */
			HibernateUtil.LOGGER.info
				("initialize hibernate session factory, class: HibernateUtil method: getSessionFactory");
			HibernateUtil.sf = new Configuration().configure(HibernateUtil.HIBERNATE_CONFIG_FILE).buildSessionFactory();
		}
		return HibernateUtil.sf;
	}
	
	/**
	 * getter method
	 * 
	 * @return hibernate session
	 */
	public static Session getCurrentSession() {
		return HibernateUtil.getSessionFactory().getCurrentSession();
	}

Oder soll ich einfach wie folgt arbeiten:
Code:
		Session session = HibernateUtil.getCurrentSession();
                session.connection().setReadOnly(true); //connection ist deprecated
 
Zuletzt bearbeitet:
Code:
session.setFlushMode(FlushMode.NEVER);
im Clientcode (also nicht in der HibernateUtils) sollte den Effekt erzielen. Ich hatte die hibernateUtils nur erwähnt, da ich auf den ersten Blick etwas verwirrt war, dass es so Umständlich ist das readOnly Flag zu setzen.

Die vielen Transaktionen die du aufmachst, sind allerdings die größere Bremse glaub ich. Hast du mal versucht, Transaktionen komplett sein zu lassen?

Gruß
Ollie
 

Neue Beiträge

Zurück