I have three Java Class, A which is the parent and B & C are subclasses of A. I have a Hibernate mapping file for A where I have mapped B & C using joined-subclass. Now when I try to query C I get [Ljava.lang.Object; cannot be cast to A. The query that Hibernate generates is correct but why it is not allowing the casting to A?
I have tried the following queries, both result in the same error.
session.createQuery("from Request as req inner join req.category where req.class=Externalrequest and req.requestId=:id");
session.createQuery("from ExternalRequest as ereq inner join ereq.category where ereq.requestId=:id");
Where Request is the parent class and ExternalRequest & InternalRequest are the child class.
And here is the basic structure of my mapping file
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Request" table="request" schema="public">
<id name="requestId" type="integer">
<column name="request_id" />
<generator class="sequence" >
<param name="sequence">request_request_id_seq</param>
</generator>
</id>
<many-to-one name="category" column="category" class="RequestCategory" />
<joined-subclass name="ExternalRequest" table="external_request">
<key column="request_id"/>
.........
</joined-subclass>
<joined-subclass name="InternalRequest" table="internal_request">
<key column="request_id"/>
.......
</joined-subclass>
</class>
[Ljava.lang.Object; is the string representation of an array of Objects.
I think what is happening is that you are trying to assign the result of the query, that is an array of Request or ExternalRequest, to a variable of class Request or ExternalRequest.
Related
I am taking an existing Java application and working on updating it from Hibernate 3 where we used hbm.xml files for Entity Mappings. We are now using Hibernate 5.5.5.Final and the code compiles with ehcache, but now I get an error with the code when starting to run it.
I should start off that one of the Hibernate properties is:
validate
The error message I am getting now is:
org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [my_db_dev.Project_myTemplateInfos]
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:121)
at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:200)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
I would love to completely remove all the hbm.xml files and replace with them with Entity Mapping POJO's with annotations, however, that is not an option right now. The existing application has this different object model that goes throughout, so I don't want to mess with that right now. That will be in the next phase.
According to the error I am missing a table named 'Project_myTemplateInfos' and there is no table with this name. Instead, there is a table named 'Project' and the hbm.xml file for this is as follows.
<hibernate-mapping package="com.myApp.server.model">
<class name="Project" table="project" dynamic-update="true">
<id name="id" column="id">
<generator class="native" />
</id>
<property name="name" not-null="true"/>
<property name="displayCity" not-null="true"/>
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<composite-element class="com.myApp.server.model.MyTemplateInfo" >
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</composite-element>
</list>
</class>
</hibernate-mapping>
As you can see 'myTemplateInfos' is a List within the Project table. After the POJO is created, it looks like something like this.
#ModelBean(IProject.class)
#PermissionIdentifier("project")
public class Project extends ModelObject implements Serializable, IProject {
private Long id;
private String displayCity = "";
private List<IMyTemplateInfo> myTemplateInfos = Lists.newArrayList();
// getters and setters
// hashcode and equals
}
Next we do have another table in the database that is called 'myTemplateInfos' and we do have an hbm xml file for that table as follows ... actually we do not have an hbm xml file for this, so maybe that is the issue. I am going to create a hbm xml file for this and see if that solves the problem.
We do have a POJO for this object 'MyTemplateInfo' though.
If I simply remove his List from the hbm mapping and the Project object, the problem goes away of course, but there is another Set in the hbm.xml file which would give me the same problem, but with a new missing table.
The question becomes how to fix this error message. Is the problem within the hbm xml file for 'Project', or is it in the Project POJO, or the fact that an hbm file does not exist for the 'MyTemplateInfo'?
The solution to this was to fix the hbm xml mapping. Since I haven't had to do this in over 15 years, I am very rusty with it. I can't tell you how happy I was back then to switch to Java POJO's for Hibernate Entity classes with Annotations. But now, unfortunately, I am back having to deal with these xml files again.
The table I had 'mycommunitytemplateinfos' I created a new hbm xml file for it as follows, and put this in the hibernate.cfg.xml file before the other hbm xml mapping.
<hibernate-mapping package="com.myapp.server.model">
<class name="MyTemplateInfo" table="mytemplateinfos">
<id name="id" column="projectId">
<generator class="native"/>
</id>
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</class>
</hibernate-mapping>
The mapping between this and the actual class is fine as I have tested this out. I put the hbm file in the hibernate.cfg.xml file before the Project.hbm.xml file and modified the Project.hbm.xml with a one-to-many tag as follows:
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<one-to-many class="com.myApp.server.model.MyTemplateInfo" />
</list>
And this seemed to work. I had to do something like this a few times until I got the mapping right. In this day of age, there isn't a lot of information about hbm xml files. Hibernate 5 does use these, but I understand that the preferred way is annotated Java POJO's. Unfortunately, I am stuck in a situation where I can't do that yet.
I'm trying based on some examples and Hibernate documentation for mapping a Stored Procedure, I just need to insert some data wich is not for a single table, but I got the message:
Could not parse mapping document from resource
The mapping file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Data">
<id column="col_id" name="dataId">
<generator class="assigned" />
</id>
<property column="col_liq" name="dataLiq" />
<property column="col_td" name="dataTd" />
<property column="col_numdcto" name="dataNumDoc" />
<sql-insert callable="true" check="none">
{call sp_update_data(?,?,?,?)}
</sql-insert>
</class>
</hibernate-mapping>
The "Data" object is just a POJO.
I will appreciate any idea or sugestion.
just to let others to know how it works due finally I did it.
The mapping is correct with just one point, Hibernate will set the Id as the last field, so the procedure should get it in that position, at least that you do some "trick".
In Java when calling the procedure is like a normal save, the rest is like working with a normal entity.
I'm very new to hibernate, and I'm trying to set up a new method in our PersonDAO.
My hibernate mapping file looks like this:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.foo.bar.domain">
<class name="Person" table="person">
<meta attribute="class-description">A Person</meta>
<id name="id" type="java.lang.Long" column="rid" unsaved-value="null">
<generator class="native" />
</id>
<version name="version" type="integer" column="rversion" unsaved-value="null" />
<property name="UID" type="string" column="UID" length="16" not-null="true" unique="true"/>
<property name="lastName" type="string" column="last_name" not-null="true" />
<property name="firstName" type="string" column="first_name" not-null="true" />
<property name="ownDepartment" type="string" column="own_department"/>
<!-- a person has many responsibilities and a responsibility can can assigned to many person -->
<set name="responsibilities" table="person_responsibility">
<key column="person_id"/>
<many-to-many column="responsibility_id" class="Responsibility"/>
</set>
<set name="additionalDepartments" table="PERSON_TO_ADDL_DEPARTMENT">
<key column="person_id"/>
<element column="ADDITIONAL_DEPARTMENT" type="string"/>
</set>
</class>
and I've written a method like this, in java, to fetch all the managers from a given department:
public List<Person> getManagerByDepartment(final String givenDepartment){
List<Person> l = (List<Person>) this.getHibernateTemplate().executeFind(new HibernateCallback<List<Person>>() {
public List<Person> doInHibernate(Session session) throws HibernateException, SQLException {
String query = "select p from Person p join p.responsibilities responsibilities join p.additionalDepartments additionalDepartments where responsibilities.name = 'manager' and (p.ownDepartment = :givenDepartment or additionalDepartments = :givenDepartment)";
List<Person> result = (List<Person>) session.createQuery(query).setString("givenDepartment", givenDepartment).list();
return result;
}
});
return l;
}
now I do a manual query in SQL, and I can see that for a given department, there are definitely more than one people who have the additional responsibility 'manager'...why does my method only ever return one person, instead of all of them?
I have a strong suspicion that my method, specifically my query, and not the mapping, is the issue, but I can't see what's wrong with it...
I've jumped in at the deep end here, so any help would be very much appreciated.
edit: note, I'm working on hundreds of records, not millions, and this isn't exactly a bottle-neck operation, so I'm not too worried about performance...that said if I'm doing something that's pointlessly wasteful, do point it out
You can print hibernate query by enabling showsql option and check the query getting created and then test it against the database.
Hard to be sure without the sample data, but when you do join in HQL, it is translated to inner join in SQL. So, if you know that there should be more than one result with given responsibility then the problem is probably join p.additionalDepartments.
Try this query with left join for additionalDepartments and see if it works
String query = "select p from Person p join p.responsibilities responsibilities left join p.additionalDepartments additionalDepartments where responsibilities.name = 'manager' and (p.ownDepartment = :givenDepartment or additionalDepartments = :givenDepartment)";
I have the following setup where a class contains a collection. When querying instances of this class I like to populate a data transfer class rather than the data class. However, Hibernate generates a wrong SQL query. What am I missing?
The Hibernate mapping:
<class name="Thread" table="tbl_threads" schema="dbo">
<id name="Id" type="integer">
<column name="i_id"/>
<generator class="identity"/>
</id>
<set name="keywords" inverse="true" lazy="false" cascade="all-delete-orphan" optimistic-lock="false">
<key>
<column name="thread_id" not-null="true"/>
</key>
<one-to-many class="Comment"/>
</set>
<!-- ... -->
</class>
and
<class name="ThreadKeyword" table="tbl_keywords" schema="dbo">
<composite-id name="id"
class="se.ericsson.eab.sdk.fido.server.api.pojos.report.ReportThreadKeywordId">
<key-property name="keywordId" type="integer">
<column name="keyword_id" />
</key-property>
<key-property name="threadId" type="integer">
<column name="thread_id" />
</key-property>
</composite-id>
<!-- ... -->
</class>
The HQL I am using is
SELECT new Composite(t.id, t.keywords, ...)
FROM Thread t, ThreadKeyword tk
WHERE t.id = tk.id.threadId
This generates a SQL where the SELECT part contains only a dot for the keyword attribute:
select thread1_.report_id as col_0_0_, . as col_92_0_
from dbo.tbl_thread reportthre0_ inner join
dbo.tbl_keywords keywords4_ on reportthre0_.i_id=keywords4_.thread_id
It works fine when I query for the data class directly, i.e.
SELECT t
FROM Thread t, ThreadKeyword tk
WHERE t.id = tk.id.threadId
As I understand will Hibernate not find a column name for keywords in the thread table. That is right, since it is a collection. It rather needs to be populated using subsequent queries. If I omit the keywords in the constructor for the Composite class the query gets right but Hibernate won't populate the Set.
How do I get the keywords set populated?
You cannot do that with a collection.
t.id is a column/value
so Hibernate translates that into thread1_.report_id as col_0_0_. Hibernate even gave it the alias col_0_0_
t.keywords is a set of values so Hibernate just can't translate the collection into a column/value.
A query includes a list of columns to be included in the final result
immediately following the SELECT keyword - Wikipedia
Now the
SELECT t FROM Thread t, ThreadKeyword tk WHERE t.id = tk.id.threadId
works fine because Hibernate knows how to translate the query you have there into SQL.
I've a Color Enum
public enum color { GREEN, WHITE, RED }
and I have MyEntity that contains it.
public class MyEntity {
private Set<Color> colors;
...
I already have a UserType to map my Enums.
Do you know how to map a Set of Enums in the Hibernate hbm.xml?
Do I need a UserType or there's an easiest way? Thanks
edit: Just to remark, I'm looking for the hbm.xml configuration not the #CollectionOfElements Annotation
I use the solution from the EnumSet mapping thread which relies on the use of <element column>. You just need a table with an id and a string to map the collection (MYENTITY_COLOR here). And the mapping looks like that (the EnumUserType is the one from Java 5 EnumUserType):
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<typedef name="color" class="com.stackoverflow.q2402869.EnumUserType">
<param name="enumClassName">com.stackoverflow.q2402869.Color</param>
</typedef>
<class name="com.stackoverflow.q2402869.MyEntity" entity-name="MyEntity" table="MYENTITY">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="assigned" />
</id>
<set name="colors" table="MYENTITY_COLORS">
<key column="ID" not-null="true"/>
<element type="color" column="COLOR"/>
</set>
</class>
</hibernate-mapping>
Query might look like this:
select distinct e from MyEntity e join e.colors colors where colors IN ('WHITE', 'GREEN')
The whole solution works well for loads, saves and queries (credits to jasonab).
It seems you need to use the #CollectionOfElements annotation. The doc is at http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype, chapter '2.4.6.2.5. Collection of element or composite elements'. The example also maps a Set of Enum.