Hibernate - nur bestimme Spalten aus DB lesen

y0dA

Erfahrenes Mitglied
Hi!
Ich bringe es einfach nicht zusammen dass ich aus einer Tabelle "I80050" einfach nur bestimmte Spalten zu lesen - Sprich der Response der DB wird dann nicht auf die Model Klasse der Tabelle "I80050" gecastet sondern es wird ein Object zurückgegeben, welches ich auch nicht auf das richtige Model casten kann. Heißt das nun dass ich extra Model anlegen muss wenn ich nicht alle Spalten lesen möchte (kann ich mir nicht vorstellen)? Wenn ich alle Spalten lese funktioniert alles..

Hier mal mein Code:

Hier das Statement zum laden der Daten
Code:
public static List<I80050Model> readBatchData() {
		Session session = HibernateUtil.getCurrentSession();
		Transaction tx = null;
		ArrayList<I80050Model> values = null;
		try {
			tx = session.beginTransaction();
	
			/* read from db */
			values = (ArrayList<I80050Model>)
				session.createQuery(I80050DB.SELECT_BATCH_COLUMNS).list();
			/* commit and close session */
			tx.commit();		
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			//FIXME Logging einbauen
			e.printStackTrace();
		} finally {
			session = null;
			tx = null;
		}
		return values;
	}

hier die Konstante von oben (es werden nicht alle Spalten zum Lesen verwendet):
Code:
	static {
		/* set batch-select statement */
		StringBuffer sb = new StringBuffer();
		sb.append(" SELECT ");
		sb.append(" id, title, forename, surname, email, valid, organization, review, locality, cc, zip, street, ");
		sb.append(" geoX, geoY, geoLat, geoLong, geo, change, constructed");
		sb.append(" FROM ");
		sb.append(I80050DB.TABLE);
		sb.append(" WHERE ");
		sb.append(I80050DB.COLUMN_VALID + " = 1 ");
		sb.append(" and (" + I80050DB.COLUMN_GEO + " <> -1 ");
		sb.append(" or  " + I80050DB.COLUMN_GEO + " IS NULL) ");
		I80050DB.SELECT_BATCH_COLUMNS = sb.toString();

mfg
 
Also so wie ich Hibernate verstanden hab und bislang damit arbeite, liest und schreibst du immer vordefinierte Objekte in die Datenbank. Es sollte eigentlich nicht ohne weiteres möglich sein zu sagen, dass man nur bestimmte Spalten will. Dies geht - soweit ich es bisher verstanden habe - nur wenn du dir ein Objekt erstellst, das für genau diese Spalten Variablen enthält und dafür dann halt wieder ein eigenes Mapping.


Ein sehr unschöner Workaround ist natürlich dir über die Session mittels .createSQLQuery() dir ein Query-Objekt geben zu lassen mit dem du dann wie gehabt SQL-Anfragen ausführen kannst und auch ganz normal ein ResultSet zurückkriegst, welches die Zeilen mit den gefragten Spalten als Objekt-Array enthält. Aber wie gesagt: das ist sehr unschön, weil du damit praktisch normales SQL machst und Hibernate gar nicht erst benutzt/brauchst.
 
Hmm...aber ist doch blöd dass man alle Spalten lesen muss obwohl man nur bspw. 2 benötigt. Vllt. verstehe ich einfach noch nicht dass Hibernate schlicht anders arbeitet/ansetzt - bei ja noch newbie diesbezüglich.
 
Hier ist mal ein kleines Beispiel. Die Modelklasse und den Rest müsstest du ja haben, da ich das hier aus deinem letzten Beispiel in einem anderen Thema übernommen habe.

Java:
package de.tutorials.hibernate;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

public class TestHibernate {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Configuration configuration = new Configuration().configure();
		configuration.setProperty("hibernate.show_sql", "true");
		SchemaExport export = new SchemaExport(configuration);
		export.create(false, true);
		SessionFactory factory = configuration.buildSessionFactory();
		Session session = factory.openSession();
		Transaction ta = session.beginTransaction();
		
		
		AdvancedAddressModel model = new AdvancedAddressModel();
		model.setId(1);
		model.setCountry("Austria");
		model.setGeoLat("lattidude");
		model.setGeoLong("longitude");
		model.setHouseNumber("34");
		model.setLocality("locality");
		model.setStreet("street");
		model.setZip("zip");
		model.setCountryCode("country code");
		session.save(model);
		
		model = null;
		
		
		ta.commit();
		
		//model = (AdvancedAddressModel)session.load(AdvancedAddressModel.class, 1); //komplettes Object aus DB lesen
		
		Query query = session.createQuery("select country from AdvancedAddressModel where id=1"); //nur eine Spalte auslesen
		List list = query.list();
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}

}

Noch was zu deinem AdvancedAddressModel, die toString-Methode sollte nicht unbedingt null zurück geben.

MFG
zEriX
 
Zuletzt bearbeitet:
Hallo,

Also so wie ich Hibernate verstanden hab und bislang damit arbeite, liest und schreibst du immer vordefinierte Objekte in die Datenbank. Es sollte eigentlich nicht ohne weiteres möglich sein zu sagen, dass man nur bestimmte Spalten will. Dies geht - soweit ich es bisher verstanden habe - nur wenn du dir ein Objekt erstellst, das für genau diese Spalten Variablen enthält und dafür dann halt wieder ein eigenes Mapping.
Mit HQL hat man die Möglichkeit in der Query einen entsprechenden Constructor-aufruf durchzuführen... dann werden IMHO auch nur die vom Constructor gesetzten Properties befüllt:
Code:
select new Family(mother, mate, offspr)
from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr

Man kann sich das auch als Maps (für jede Zeile eine,..) geben lassen:
Code:
select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
from Cat cat

Siehe:
http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#queryhql-tuple

Gruß Tom
 
Hallo,


Mit HQL hat man die Möglichkeit in der Query einen entsprechenden Constructor-aufruf durchzuführen... dann werden IMHO auch nur die vom Constructor gesetzten Properties befüllt:
Code:
select new Family(mother, mate, offspr)
from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr
Hmm..
Code:
new Family(mother, mate, offspr)
die parameter gehören dann wohl gesetzt - wäre unlogisch! Somit nehme ich an dass das alles ein String wäre, jedoch folgendes klappt nicht:

Code:
values = (ArrayList<I80050Model>)
				session.createQuery("SELECT" +
						" I80050Model(id, title, forename, surname, email, valid, organization, review, locality, cc, zip, street," +
						" geoLat, geoLong, geo, change, constructed)" +
					"FROM I80050Model");

Stacktrace:
java.lang.IllegalStateException: No data type for node: org.hibernate.hql.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: '('
+-[METHOD_NAME] IdentNode: 'I80050Model' {originalText=I80050Model}
\-[EXPR_LIST] SqlNode: 'exprList'
+-[DOT] DotNode: 'i80050mode0_.ID' {propertyName=id,dereferenceType=4,propertyPath=id,path={synthetic-alias}.id,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'id' {originalText=id}
+-[DOT] DotNode: 'i80050mode0_.TITEL' {propertyName=title,dereferenceType=4,propertyPath=title,path={synthetic-alias}.title,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'title' {originalText=title}
+-[DOT] DotNode: 'i80050mode0_.VORNAME' {propertyName=forename,dereferenceType=4,propertyPath=forename,path={synthetic-alias}.forename,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'forename' {originalText=forename}
+-[DOT] DotNode: 'i80050mode0_.ZUNAME' {propertyName=surname,dereferenceType=4,propertyPath=surname,path={synthetic-alias}.surname,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'surname' {originalText=surname}
+-[DOT] DotNode: 'i80050mode0_.EMAIL' {propertyName=email,dereferenceType=4,propertyPath=email,path={synthetic-alias}.email,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'email' {originalText=email}
+-[DOT] DotNode: 'i80050mode0_.GUELTIG' {propertyName=valid,dereferenceType=4,propertyPath=valid,path={synthetic-alias}.valid,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'valid' {originalText=valid}
+-[DOT] DotNode: 'i80050mode0_.ORGANISATION' {propertyName=organization,dereferenceType=4,propertyPath=organization,path={synthetic-alias}.organization,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'organization' {originalText=organization}
+-[DOT] DotNode: 'i80050mode0_.REVIEW' {propertyName=review,dereferenceType=4,propertyPath=review,path={synthetic-alias}.review,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'review' {originalText=review}
+-[DOT] DotNode: 'i80050mode0_.ORT' {propertyName=locality,dereferenceType=4,propertyPath=locality,path={synthetic-alias}.locality,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'locality' {originalText=locality}
+-[DOT] DotNode: 'i80050mode0_.CC' {propertyName=cc,dereferenceType=4,propertyPath=cc,path={synthetic-alias}.cc,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'cc' {originalText=cc}
+-[DOT] DotNode: 'i80050mode0_.PLZ' {propertyName=zip,dereferenceType=4,propertyPath=zip,path={synthetic-alias}.zip,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'zip' {originalText=zip}
+-[DOT] DotNode: 'i80050mode0_.STRASSE' {propertyName=street,dereferenceType=4,propertyPath=street,path={synthetic-alias}.street,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'street' {originalText=street}
+-[DOT] DotNode: 'i80050mode0_.GEO_LAT' {propertyName=geoLat,dereferenceType=4,propertyPath=geoLat,path={synthetic-alias}.geoLat,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'geoLat' {originalText=geoLat}
+-[DOT] DotNode: 'i80050mode0_.GEO_LONG' {propertyName=geoLong,dereferenceType=4,propertyPath=geoLong,path={synthetic-alias}.geoLong,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'geoLong' {originalText=geoLong}
+-[DOT] DotNode: 'i80050mode0_.GEO' {propertyName=geo,dereferenceType=4,propertyPath=geo,path={synthetic-alias}.geo,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'geo' {originalText=geo}
+-[DOT] DotNode: 'i80050mode0_.AENDERUNG' {propertyName=change,dereferenceType=4,propertyPath=change,path={synthetic-alias}.change,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
| +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
| \-[IDENT] IdentNode: 'change' {originalText=change}
\-[DOT] DotNode: 'i80050mode0_.ERSTELLT' {propertyName=constructed,dereferenceType=4,propertyPath=constructed,path={synthetic-alias}.constructed,tableAlias=i80050mode0_,className=at.pcd.wam.technologie.persistence.model.I80050Model,classAlias=null}
+-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
\-[IDENT] IdentNode: 'constructed' {originalText=constructed}


Nehme an dass ich da war falsch verstanden habe?
 
Hmpf..
Naja nach der "new" Hinzufügung bekomme ich nun folgende Exception:

java.lang.ClassCastException: org.hibernate.impl.QueryImpl
at at.pcd.wam.technologie.persistence.db.I80050DB.readBatchData(I80050DB.java:123)
at at.pcd.wam.technologie.controller.model.ClientModel.readBatchData(ClientModel.java:224)
at at.pcd.wam.technologie.controller.model.ClientModel.doValidation(ClientModel.java:123)
at at.pcd.wam.technologie.controller.ClientController.doServiceAndUpdate(ClientController.java:88)
at at.pcd.wam.technologie.batch.RunBatch.main(RunBatch.java:32)

der Konstruktor:
Code:
public I80050Model(final int id, final String title, final String forename, final String surname,
			final String email, final Integer valid, final String organization, final Integer review,
			final String locality, final String cc, final String zip, final String street, final Double geoLat,
			final Double geoLong, final Integer geo, final Date change, final Date constructed) {
		super();
		this.id = id;
		this.title = title;
		this.forename = forename;
		this.surname = surname;
		this.email = email;
		this.valid = valid;
		this.organization = organization;
		this.review = review;
		this.locality = locality;
		this.cc = cc;
		this.zip = zip;
		this.street = street;
		this.geoLat = geoLat;
		this.geoLong = geoLong;
		this.geo = geo;
		this.change = change;
		this.constructed = constructed;
	}

Ok, die ClassCastException rührte von java.util.Date - hab ich nun auf java.sql.Date geändert, nun gibts folgende Meldung :

SCHWERWIEGEND: Unable to locate appropriate constructor on class [at.pcd.wam.technologie.persistence.model.I80050Model]
[cause=org.hibernate.PropertyNotFoundException: no appropriate constructor in class: at.pcd.wam.technologie.persistence.model.I80050Model]
org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [at.pcd.wam.technologie.persistence.model.I80050Model] [SELECT new I80050Model(id, title, forename, surname, email, valid, organization, review, locality,cc, zip, street, geoLat, geoLong, geo, change, constructed)FROM at.pcd.wam.technologie.persistence.model.I80050Model]
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:31)
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:24)
at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:59)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:235)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:160)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy12.createQuery(Unknown Source)
at at.pcd.wam.technologie.persistence.db.I80050DB.readBatchData(I80050DB.java:123)
at at.pcd.wam.technologie.controller.model.ClientModel.readBatchData(ClientModel.java:224)
at at.pcd.wam.technologie.controller.model.ClientModel.doValidation(ClientModel.java:123)
at at.pcd.wam.technologie.controller.ClientController.doServiceAndUpdate(ClientController.java:88)
at at.pcd.wam.technologie.batch.RunBatch.main(RunBatch.java:32)

Aber Konstruktor existiert ja...



***EDIT***
Ok hab meinen Fehler schon entdeckt!

Mittlerweile klappt alles.
dankeschän
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück