I need a HQL Query but I just dont get it.
SELECT * FROM Poll WHERE pid NOT IN (
SELECT pid FROM votes WHERE uid = 'theuserid')
I want all List of PollĀ“s back where the uid not in the table votes exists.
Also helpfull would be the hql query where the uid in the table votes exists, but I guess this is very similar ;-)
These are the 2 classes:
public class Poll {
private int pid;
private String name;
private String description;
private Date deadline;
private Set<Team> teams = new HashSet<Team>(0);
//some getter & setter
}
public class Vote {
private int vid;
private String uid;
private int pid;
private int tid;
private int votes;
//some getter & setter
}
Can smbdy please help me. I guess it is a join with a WHERE and NOT LIKE but I just dont get it.
Merci!
This is btw the hibernate mapping:
<hibernate-mapping>
<class name="package.model.Poll" table="poll">
<id name="pid" column="pid" >
<generator class="increment"/>
</id>
<property name="name" column="name" />
<property name="description" column="description" />
<property name="deadline" type="timestamp" column="deadline" />
<set name="teams" table="pollchoice"
inverse="false" lazy="false" fetch="select" cascade="all" >
<key>
<column name="pid" not-null="true" />
</key>
<many-to-many entity-name="knt.exceedvote.model.Team">
<column name="tid" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="package.model.Vote" table="votes">
<id name="vid" column="vid" >
<generator class="increment"/>
</id>
<property name="pid" column="pid" />
<property name="uid" column="uid" />
<property name="tid" column="tid" />
<property name="votes" column="votes" />
</class>
</hibernate-mapping>
Please keep in mind, Hibernate is designed using the notion of Object Graph, which is a name given to the relational objects.
That core concept is missing in your mapping (Poll and Vote seem to be isolated) hence I doubt you can use HQL in its current state.
In my opinion, you have two options:
Define the relationship between Poll, pid and Vote, uid. Then you should be able to write simple HQL.
Use native SQL through Hibernate session itself.
Related
i want to do a left outer join from 2 table, but with 2 key that are not primary key.
This is the native sql query used:
Maybe there is a better way to do it?
SQLQuery query = session.createSQLQuery("
select {A.*},{B.*} from A_TABLE A left outer join B_TABLE B on A.QUOTE_ID = B.QUOTE_NUM ")
.addEntity("A", A_Class.class)
.addJoin("B", "A.bDocs");
for(Object result : query.list())
{
....
}
The mapping A file:
<class name="A_Class" table="A_TABLE" schema="S">
<id name="rowId" type="string">
<column name="ROW_ID" length="60" />
<generator class="assigned" />
</id>
<set name="BDocs" inverse="true" fetch="select" lazy="false">
<key>
<column name="QUOTE_NUM" length="60" not-null="true" />
</key>
<one-to-many class="B_Class" />
</set>
A_Class.java
public class A_Class implements java.io.Serializable
{
private String rowId;
private String QuoteId;
private Set BDocs= new HashSet(0);
// omitted all the set and get
}
The mapping B file:
<hibernate-mapping>
<class name="B" table="B_TABLE" schema="S">
<id name="rowId" type="string">
<column name="ROW_ID" length="60" />
<generator class="assigned" />
</id>
<many-to-one name="A" class="A_Class" fetch="select" lazy="false" outer-join="true" foreign-key="QuoteId" property-ref="QuoteId">
<column name="QUOTE_NUM" length="60" not-null="true" />
</many-to-one>
B_Class.java
public class B_Class implements java.io.Serializable
{
private String rowId;
private String quoteNum;
// omitted all the set and get
}
From this query i obtain 2 objects, one of A type and the other of B Type with a lot of correct datas but the set BDocs in the object of A type isn't filled. The goal is to get only the A Object with the variable BDocs filled with the B Objects.
I don't understand if the problem is in the query or in the mapping files. Anyone can help me?
I am trying to retrieve the count of items allocated to a container in my hbm file. I've done a bit of digging and managed to get my hbm code this far (below!). I want the count to be retrieved every time a container object is queried. I could use an interceptor but I assume there's a better way. Am I on the right track or should I use a different strategy to get the count loaded up?
Thanks.
P.S. We're using NH v2.2
<?xml version="1.0" encoding="utf-8"?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" assembly="MyEntities" namespace="Entities.Containers"> <class name="Container" table="[Container]" xmlns="urn:nhibernate-mapping-2.2">
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="Capacity" column="Capacity">
<column name="Capacity" />
</property>
<property name="Description" column="Description" length="50" type="String">
<column name="Description" />
</property>
<loader query-ref="sqCurrentContainerAllocation"/> </class>
<sql-query name="sqCurrentContainerAllocation">
<return-scalar column="AllocatedItemsCount" type="int"></return-scalar>
SELECT COUNT(*) FROM [ContainerTracking]
WHERE [ContainerId] = :Id </sql-query>
</hibernate-mapping>
If you need to get some calculated property, you can use mapping with formula.
Let's extend your C# class:
public class Container
{
... // ID, Capacity, Description
public virtual int MyCount { get; set; }
And extend your mapping
<class name="Container" table="[Container]"
...
<property name="MyCount" insert="false" update="false" >
<formula>
(
SELECT count(*)
FROM [ContainerTracking] as ct
WHERE ct.[ContainerId] = Id
)
</formula>
</property>
the Id will be replaced with somethink like '_this.Id', the name of the column Id and its alias
This will of course load the count all the time (except projections) so think twice before use it
I think the object model below is saying a Party and PartyName to have a many to one relatioship. An I think the cascade=all i the Party.hbm sshould be having NHib save the child PartyName(s).
But it clearly isn't...
Can someone explain why PartyName isn't being saved with Party and what to do to fix?
Cheers,
Berryl
MAPPING
<class name="Party" table="Parties">
<id name="Id">
<column name="PartyId" />
<generator class="hilo" />
</id>
<discriminator column="Type" not-null="true" type="string" />
<set access="field.camelcase-underscore" cascade="all" inverse="true" name="Names">
<key foreign-key="Party_PartyName_FK">
<column name="PartyNameId" />
</key>
<one-to-many class="Parties.Domain.Names.PartyName, Parties.Domain" />
</set>
<subclass
name="Smack.Core.TestingSupport.NHibernate.TestableDomain.SomeDopeyDomainModel.Student, Smack.Core.TestingSupport"
discriminator-value="Student"
>
<property name="Number" />
<many-to-one
class="Smack.Core.TestingSupport.NHibernate.TestableDomain.SomeDopeyDomainModel.Course, Smack.Core.TestingSupport"
foreign-key="Course_FK"
name="Course">
<column name="CourseId" index="CourseIndex" />
</many-to-one>
</subclass>
<many-to-one access="field.camelcase-underscore" class="Parties.Domain.Party" foreign-key="Party_FK" name="Party">
<column name="PartyId" index="PartyIndex" not-null="true"/>
</many-to-one>
<property name="TheRequiredName" not-null="true" length="50"/>
<property name="EverythingElse" />
<property name="ContextUsed" length="50"/>
<property name="Salutation" length="20"/>
<property name="EffectivePeriod" type="Smack.Core.Data.NHibernate.UserTypes.DateRangeUserType, Smack.Core.Data">
<column name="EffectiveStart"/>
<column name="EffectiveEnd"/>
</property>
Failing Test (and output)
[Test]
public void CanSaveAndLoad_AllProperties()
{
var partyName = NameSeeds.DevName;
partyName.Party = _party;
Assert.That(_party.Names.First(), Is.EqualTo(partyName));
using (var tx = _session.BeginTransaction())
{
_session.Save(_party);
tx.Commit();
}
_session.Clear();
Party foundParty;
using (var tx = _session.BeginTransaction())
{
foundParty = _session.Get<Party>(_party.Id); *** <=== name s/b saved!!
tx.Commit();
}
PartyName foundName = foundParty.Names.First();
//found.Look();
Assert.That(foundName, Is.EqualTo(partyName));
Assert.That(foundName.Party, Is.Not.Null);
Assert.That(foundName.TheRequiredName, Is.EqualTo(partyName.TheRequiredName));
Assert.That(foundName.EverythingElse, Is.EqualTo(partyName.EverythingElse));
Assert.That(foundName.ContextUsed, Is.EqualTo(partyName.ContextUsed));
Assert.That(foundName.Salutation, Is.EqualTo(partyName.Salutation));
Assert.That(foundName.EffectivePeriod, Is.EqualTo(partyName.EffectivePeriod));
}
NHibernate: INSERT INTO Parties (Type, PartyId) VALUES ('Parties.Domain.Party', #p0);#p0 = 32768 [Type: Int32 (0)]
NHibernate: SELECT party0_.PartyId as PartyId2_0_, party0_.Number as Number2_0_, party0_.CourseId as CourseId2_0_, party0_.Type as Type2_0_ FROM Parties party0_ WHERE party0_.PartyId=#p0;#p0 = 32768 [Type: Int32 (0)]
With the mapping of the Names <set> inverse=true, you will have to explicitly call session.Save(partyNameObject) on each member of the collection. If you are looking to have NHibernate automatically save the members of the set when the PartyObject is saved, you need to change the Names <set> inverse attribute to inverse=false. This tells Nhibernate that you want Party to control the relationship between Party and PartyName. You must also remember to add each partyNameObject to the Party.Names collection. Otherwise, they won't be saved when you call Session.Save(partyObject). Keep in mind that having the parent control the relationship may be handy, but if you happen to save the PartyObject without having Loaded the PartyNames collection, NHibernate will update their Party FK to Null. In this scenario with certain Cascade options set on the Names <set>, you might find Nhibernate Deleting them as well.
I am customizing N2CMS's database structure, and met with an issue. The two classes are listed below.
public class Customer : ContentItem
{
public IList<License> Licenses { get; set; }
}
public class License : ContentItem
{
public Customer Customer { get; set; }
}
The nhibernate mapping are as follows.
<class name="N2.ContentItem,N2" table="n2item">
<cache usage="read-write" />
<id name="ID" column="ID" type="Int32" unsaved-value="0" access="property">
<generator class="native" />
</id>
<discriminator column="Type" type="String" />
</class>
<subclass name="My.Customer,My" extends="N2.ContentItem,N2" discriminator-value="Customer">
<join table="Customer">
<key column="ItemID" />
<bag name="Licenses" generic="true" inverse="true">
<key column="CustomerID" />
<one-to-many class="My.License,My"/>
</bag>
</join>
</subclass>
<subclass name="My.License,My" extends="N2.ContentItem,N2" discriminator-value="License">
<join table="License" fetch="select">
<key column="ItemID" />
<many-to-one name="Customer" column="CustomerID" class="My.Customer,My" not-null="false" />
</join>
</subclass>
Then, when get an instance of Customer, the customer.Licenses is always empty, but actually there are licenses in the database for the customer. When I check the nhibernate log file, I find that the SQL query is like:
SELECT licenses0_.CustomerID as CustomerID1_,
licenses0_.ID as ID1_,
licenses0_.ID as ID2_0_,
licenses0_1_.CustomerID as CustomerID7_0_,
FROM n2item licenses0_
inner join License licenses0_1_
on licenses0_.ID = licenses0_1_.ItemID
WHERE licenses0_.CustomerID = 12 /* #p0 */
It seems that nhibernate believes that the CustomerID is in the 'n2item' table. I don't know why, but to make it work, I think the SQL should be something like this.
SELECT licenses0_.ID as ID1_,
licenses0_.ID as ID2_0_,
licenses0_1_.CustomerID as CustomerID7_0_,
FROM n2item licenses0_
inner join License licenses0_1_
on licenses0_.ID = licenses0_1_.ItemID
WHERE licenses0_1_.CustomerID = 12 /* #p0 */
Could any one point out what's wrong with my mappings? And how can I get the correct licenses of one customer? Thanks in advance.
I'm not sure whether the SQL is incorrect, because the parent class mapping uses a discriminator so I'd expect all properties to be stored in the same table as the base class (n2item). However I'm not familiar with the "join table" syntax, I generally use joined-subclass so I might be misunderstanding.
Assuming the subclass mapping is correct, could the problem with the licenses be something to do with no Cascade setting being set for that collection?
Considering the following mapping file where TemporaryAccessOpenCommand and TemporaryAccessCloseCommand both inherit from base class Command
<class name="Command" table="xxx_Commands" lazy="false">
<id name="Id" type="Int32" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="BeginDate" />
<property name="EndDate" />
<component name="Result" class="CommandResult">
<property name="Status" column="ResultStatus"/>
<property name="Details" column="ResultDetails" />
</component>
<many-to-one name="Requestor" class="xxx.Domain.SessionInfo, xxx.Domain" column="SessionInfoId" lazy="false" />
<joined-subclass name="xxx.TemporaryAccess.Commands.TemporaryAccessCloseCommand, xxx.TemporaryAccess" table="xxx_Commands_TemporaryAccess_Close">
<key column="CommandId"/>
</joined-subclass>
<joined-subclass name="xxx.TemporaryAccess.Commands.TemporaryAccessOpenCommand, xxx.TemporaryAccess" table="xxx_Commands_TemporaryAccess_Open">
<key column="CommandId"/>
<many-to-one name="EndUser" ...... />
<property name="Reason"/>
<property name="AccessRight"/>
<property name="AccessType"/>
<bag name="CloseAccessCommands" cascade="all" lazy="false">
<key column="OpenCommandId"/>
<one-to-many class="xxx.TemporaryAccess.Commands.TemporaryAccessCloseCommand, xxx.TemporaryAccess"/>
</bag>
</joined-subclass>
What would be the nhibernate query to retrieve every OpenAccessCommand having no succeeded CloseAccessCommand ?
I tried this :
public IList<TemporaryAccessOpenCommand> FindOpenCommandsWithoutSucceededCloseCommand()
{
return this.HibernateTemplate.ExecuteFind<TemporaryAccessOpenCommand>(delegate(ISession session)
{
return session.CreateCriteria(typeof(TemporaryAccessOpenCommand))
.CreateCriteria("CloseAccessCommands")
.Add(Expression.Not(Expression.Eq("Result.Status", CommandStatus.Succeeded)))
.List<TemporaryAccessOpenCommand>();
});
}
But it will return an OpenAccessCommand that has tow CloseCommand (one failed and one succeeded) when it should return an empty list.
Thanks for your help (and excuse my poor english)
I managed to get something working this way (I'm open to suggestions if it's not the best way)
public IList<TemporaryAccessOpenCommand> FindOpenCommandsWithoutSucceededCloseCommand()
{
return this.HibernateTemplate.ExecuteFind<TemporaryAccessOpenCommand>(delegate(ISession session)
{
string sql = string.Format(#"
(
SELECT temp_c.OpenCommandId
FROM VSA2_Commands_TemporaryAccess_Close temp_c
INNER JOIN VSA2_Commands c
ON temp_c.CommandId = c.Id
WHERE c.ResultStatus = {0}
) AS OpenCommandId"
, (int)CommandStatus.Succeeded);
var subCriteria = DetachedCriteria.For<TemporaryAccessCloseCommand>();
subCriteria = subCriteria.SetProjection(Projections.SqlProjection(sql, new string[] { "OpenCommandID" }, new IType[] { NHibernateUtil.Int32 }));
return session.CreateCriteria(typeof(TemporaryAccessOpenCommand))
.Add(Expression.Eq("Result.Status", CommandStatus.Succeeded))
.Add(Subqueries.PropertyNotIn("Id", subCriteria))
.List<TemporaryAccessOpenCommand>();
});
}