New to Hibernate here, so it might be that I just misunderstood and/or made a mistake somewhere.
Recently I implemented Hibernate in my standalone Java application. I have a complicated database structure with a lot of associations, and one super-subclass-construction, with each their own tables. The problem is as follows:
When I ask Hibernate to select a couple of rows from one of the subclass-tables, I get an Id per row that is not the same as the one in the database. This results in a lot of problems when I want to use this Id elsewhere (getting foreign key violations). The Id is always the same for that specific row, though I cannot find the Id anywhere in the database, not in the same table or in others.
My Hibernate mapping for the super/subclass is as follows:
<?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="bliksem_prototype.model.Endpoint" table="Bliksem_Endpoint" schema="dbo" catalog="WMB_Application_Operations_ONTW" optimistic-lock="version">
<id name="endpointId">
<column name="EndpointId" length="36" />
<generator class="uuid2" />
</id>
<property name="endpointType" type="string">
<column name="EndpointType" length="30" not-null="true" />
</property>
<set name="endpointFlows" table="Bliksem_Link_Endpoint_Flow" inverse="true" lazy="true" fetch="select">
<key>
<column name="EndpointId" length="36" not-null="true" />
</key>
<one-to-many class="bliksem_prototype.model.EndpointFlow" />
</set>
<joined-subclass name="bliksem_prototype.model.Queue" table="Bliksem_Queue" schema="dbo" catalog="WMB_Application_Operations_ONTW" extends="bliksem_prototype.model.Endpoint">
<key column="QueueId"/>
<many-to-one name="cluster" class="bliksem_prototype.model.Cluster" fetch="select">
<column name="ClusterName" length="30" />
</many-to-one>
<many-to-one name="queueManager" class="bliksem_prototype.model.QueueManager" fetch="select">
<column name="QueueManagerName" length="30" not-null="true" />
</many-to-one>
<property name="queueName" type="string">
<column name="QueueName" length="70" not-null="true" />
</property>
<property name="queueType" type="string">
<column name="QueueType" length="30" not-null="true" />
</property>
<property name="maxDepth" type="java.lang.Long">
<column name="MaxDepth" precision="10" scale="0" />
</property>
<property name="maxMessageLength" type="java.lang.Long">
<column name="MaxMessageLength" precision="15" scale="0" />
</property>
<set name="queueDestinationRouters" table="Bliksem_Link_Queue_DestinationRouter" inverse="true" lazy="true" fetch="select">
<key>
<column name="QueueId" length="36" not-null="true" />
</key>
<one-to-many class="bliksem_prototype.model.QueueDestinationRouter" />
</set>
</joined-subclass>
<joined-subclass name="bliksem_prototype.model.FileNode" table="Bliksem_FileNode" schema="dbo" catalog="WMB_Application_Operations_ONTW" extends="bliksem_prototype.model.Endpoint">
<key column="FileNodeId"/>
<property name="fileNodeName" type="string">
<column name="FileNodeName" length="70" not-null="true" />
</property>
<property name="mapName" type="string">
<column name="MapName" length="70" />
</property>
</joined-subclass>
<joined-subclass name="bliksem_prototype.model.Webservice" table="Bliksem_Webservice" schema="dbo" catalog="WMB_Application_Operations_ONTW" extends="bliksem_prototype.model.Endpoint">
<key column="WebserviceId"/>
<property name="webserviceName" type="string">
<column name="WebserviceName" length="70" not-null="true" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
If I change the generator class to assigned and assign the UUID myself, I still get the same problem.
Example of one of the subclasses:
public class FileNode extends Endpoint implements java.io.Serializable, Comparable<FileNode> {
private String fileNodeName;
private String mapName;
public FileNode() {
}
public FileNode(UUID fileNodeId, String fileNodeName, String mapName) {
super(fileNodeId, "FileNode");
this.fileNodeName = fileNodeName;
this.mapName = mapName;
}
public FileNode(UUID fileNodeId, String fileNodeName) {
super(fileNodeId, "FileNode");
this.fileNodeName = fileNodeName;
}
public String getFileNodeName() {
return this.fileNodeName;
}
public void setFileNodeName(String fileNodeName) {
this.fileNodeName = fileNodeName;
}
public String getMapName() {
return this.mapName;
}
public void setMapName(String mapName) {
this.mapName = mapName;
}
#Override
public int compareTo(FileNode o) {
return this.getFileNodeName().compareTo(o.getFileNodeName());
}
}
Superclass:
public class Endpoint implements java.io.Serializable {
private UUID endpointId;
private String endpointType;
private Set endpointFlows = new HashSet(0);
#Transient
private String environmentName;
public Endpoint() {
}
public Endpoint(UUID endpointId, String endpointType, Set endpointFlows) {
this.endpointId = endpointId;
this.endpointType = endpointType;
this.endpointFlows = endpointFlows;
}
public Endpoint(UUID endpointId, String endpointType) {
this.endpointId = endpointId;
this.endpointType = endpointType;
}
public Endpoint(UUID endpointId, String endpointType, String environmentName) {
this.endpointId = endpointId;
this.endpointType = endpointType;
this.environmentName = environmentName;
}
public UUID getEndpointId() {
return endpointId;
}
public void setEndpointId(UUID endpointId) {
this.endpointId = endpointId;
}
public String getEndpointType() {
return this.endpointType;
}
public void setEndpointType(String endpointType) {
this.endpointType = endpointType;
}
public String getEnvironmentName() {
return environmentName;
}
public void setEnvironmentName(String environmentName) {
this.environmentName = environmentName;
}
public Set getEndpointFlows() {
return endpointFlows;
}
public void setEndpointFlows(Set endpointFlows) {
this.endpointFlows = endpointFlows;
}
}
Inserting one of the subclasses works perfectly, I don't have to insert the superclass which goes automatically.
Note: I'm not entirely sure if my problem is only because of the super/subclass construction, but this is the first time I ran across some problems with it.
What am I missing or not understanding correctly about Hibernate?
After some more testing, I suddenly realized that the key given by Hibernate and the one in the database contained the same characters, just in a different order. After another search on Google, I found this topic:
Problem obtaining entities with uniqueidentifier primary key
It seems that this is the case: The Java UUID (java.util.UUID) and the SQL Server uniqueidentifier are two different things. Somehow Hibernate manages to map the characters, but not the order (though the final part of both keys were the same). I solved my problem by the answer that wasn't accepted as an answer, and added type="uuid-char", and it works. I can also let Hibernate generate the UUID with <generator class="uuid2" />.
I do want to note that the type="uuid-char" might not even be necessary, as Hibernate does seem to do mapping without it (though it might be confusing). If you use uuid-char, it is also necessary to cast parameters to String when calling the database with hql/query using Hibernate and asking for a row by the UUID. If you fill in the UUID as parameter, you might not get a result.
Related
Simple pojo class
package practice041116;
public class Cls {
public String name;
public int roll;
public Cls(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRoll() {
return roll;
}
public void setRoll(int roll) {
this.roll = roll;
}
}
The main login file
package practice041116;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.SessionFactory;
public class MainClass {
public static void main(String args[]){
Configuration cnfg=new Configuration();
cnfg.configure("hibernate.cfg.xml");
SessionFactory fact=cnfg.buildSessionFactory();
Session session=fact.openSession();
Transaction tx=session.beginTransaction();
Cls s=new Cls();
s.setName("Taleev");
s.setRoll(23);
session.save(s);
tx.commit();
}
}
The configuration file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate
Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-
configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">
com.microsoft.sqlserver.jdbc.SQLServerDriver
</property>
<property name="hibernate.connection.url">
jdbc:microsoft:sqlserver://171.8.9.1;DatabaseName:test
</property>
<property name="hibernate.connection.username">
username
</property>
<property name="hibernate.connection.password">
password
</property>
<property name="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</property>
<property name="show_sql">true</property>
<mapping resource="practice041116/Cls.hbm.xml" />
</session-factory>
</hibernate-configuration>
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="Cls" table="cls">
<id name="id" column="id" type="integer"/>
<property name="name" column="NAME" type="string"/>
<property name="roll" column="ROLL" type="integer"/>
</class>
</hibernate-mapping>
I have the specified table in my database but while execute it gives Entity Class not found Exception, i have tried various answer available on the similar question such as this one
and few more from other sources from the net
Hierarchy of the project and the jar files used
Thanks in advance and forgive me if i have done some format mistake on this question as this is the first question i am posting.
Stack trace of Exception
In your mapping file :
<class name="Cls" table="cls">
you don't specify qualified class name but just simple class name.
You should replace by :
<class name="practice041116.Cls" table="cls">
Hibernate is an ORM framework which maps a Java Object (Entity Object) to a relational database table, as you did NOT map any Entity Class to a database table you are getting this exception.
Option(1): Using Annotations
You need to use #Entity (class level mapping) and #Column (element level mapping) to map the java object to a database table.
Option(2): Using mapping xml files
As sugested by David above and also you can look at here
I am running into a NucleusUserException while querying an entity from DB. I have tried a long time and couldn't figure out what caused this problem. I am hoping some of you can point me into the right direction. Any help will be greatly appreciated
Entity Class
#PersistenceCapable(detachable = "true")
public class Position implements IsSerializable, Serializable {
#PrimaryKey
#Persistent
protected String key;
#Persistent
protected Double quantity;
// getter and setter omitted
}
JDO MetaData
<jdo xmlns="http://java.sun.com/xml/ns/jdo/jdo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jdo/jdo
http://java.sun.com/xml/ns/jdo/jdo_3_0.xsd">
<package name="org.sly.main.shared.data.finance.trading">
<class name="Position" detachable="true" cacheable="false">
<version strategy="version-number" />
<field name="key" persistence-modifier="persistent"
value-strategy="increment" primary-key="true">
<column length="32" jdbc-type="VARCHAR" />
</field>
<field name="quantity" persistence-modifier="persistent" />
</class>
</package>
</jdo>
The code that i used to retrieved
PersistenceManager pm = pmf.getPersistenceManager();
Extent e = pm.getExtent(Position.class, true);
Query query = pm.newQuery(e);
query.setFilter("key == my_key");
query.declareParameters("String my_key");
Object[] params = { "1234" };
List<Position> managerList = (List<Position>) query.executeWithArray(params);
The Exception i Got is below:
Cannot find mapping for field org.sly.main.shared.data.finance.trading.Position.key in table `POSITION` [`POSITION`.`KEY`, `POSITION`.`QUANTITY`]
org.datanucleus.exceptions.NucleusUserException: Cannot find mapping for field org.sly.main.shared.data.finance.trading.Position.key in table `POSITION` [`POSITION`.`KEY`, `POSITION`.`QUANTITY`]
at org.datanucleus.store.rdbms.table.AbstractClassTable.addApplicationIdUsingClassTableId(AbstractClassTable.java:233)
at org.datanucleus.store.rdbms.table.ClassTable.initializePK(ClassTable.java:1031)
at org.datanucleus.store.rdbms.table.ClassTable.preInitialize(ClassTable.java:246)
at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.addClassTable(RDBMSStoreManager.java:3146)
at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.addClassTables(RDBMSStoreManager.java:2937)
at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.addClassTablesAndValidate(RDBMSStoreManager.java:3210)
at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.run(RDBMSStoreManager.java:2869)
at org.datanucleus.store.rdbms.AbstractSchemaTransaction.execute(AbstractSchemaTransaction.java:122)
at org.datanucleus.store.rdbms.RDBMSStoreManager.addClasses(RDBMSStoreManager.java:1606)
at org.datanucleus.store.AbstractStoreManager.addClass(AbstractStoreManager.java:954)
at org.datanucleus.store.AbstractStoreManager.getSubClassesForClass(AbstractStoreManager.java:1693)
at org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator.getStatement(DiscriminatorStatementGenerator.java:306)
at org.datanucleus.store.rdbms.scostore.JoinListStore.getIteratorStatement(JoinListStore.java:964)
at org.datanucleus.store.rdbms.scostore.JoinListStore.listIterator(JoinListStore.java:691)
at org.datanucleus.store.rdbms.scostore.AbstractListStore.listIterator(AbstractListStore.java:92)
at org.datanucleus.store.rdbms.scostore.AbstractListStore.iterator(AbstractListStore.java:82)
at org.datanucleus.store.types.backed.ArrayList.loadFromStore(ArrayList.java:294)
at org.datanucleus.store.types.backed.ArrayList.initialise(ArrayList.java:243)
at org.datanucleus.store.types.SCOUtils.createSCOWrapper(SCOUtils.java:256)
at org.datanucleus.store.types.SCOUtils.newSCOInstance(SCOUtils.java:142)
at org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping.replaceFieldWithWrapper(AbstractContainerMapping.java:399)
at org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping.postFetch(AbstractContainerMapping.java:417)
at org.datanucleus.store.rdbms.request.FetchRequest.execute(FetchRequest.java:420)
at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.fetchObject(RDBMSPersistenceHandler.java:324)
at org.datanucleus.state.AbstractStateManager.loadFieldsFromDatastore(AbstractStateManager.java:1122)
at org.datanucleus.state.JDOStateManager.loadUnloadedFieldsInFetchPlan(JDOStateManager.java:3000)
at org.datanucleus.state.JDOStateManager.isLoaded(JDOStateManager.java:3214)
Not sure will this help but this is run on AWS Elastic Mapreduce Hadoop cluster
Please help me,i really need help...
I create a composite-id in hibernate.Here are things i have
PurchasedTestId.java
package jp.go.mhlw.vaccine.draft;
import java.io.Serializable;
public class PurchasedTestId implements Serializable {
private static final long serialVersionUID = 1L;
private Long testId;
private Long customerId;
// an easy initializing constructor
public PurchasedTestId(Long testId, Long customerId) {
this.testId = testId;
this.customerId = customerId;
}
// generate setters and getters here
}
And here is my vaccin.hbm.xml file
<class name="jp.go.mhlw.vaccine.draft.PurchasedTestttt" table="PurchasedTesttt">
<composite-id name="purchasedTestId" class="jp.go.mhlw.vaccine.draft.PurchasedTestId">
<key-property name="testId" >
<column name="testId" ></column>
</key-property>
<key-property name="customerId" column="customerId" />
</composite-id>
<property name="name" column="name" type="string" />
</class>
I am using Ant build (using bulld.xml file) to generate Domain class and DB shema,only class PurchasedTestttt will be generated in my case,I've created the class PurchasedTestId before.
Whenever i start to run tools it throws
org.hibernate.MappingException: class jp.go.mhlw.vaccine.draft.PurchasedTestId not found while looking for property: testId
But in my vaccin.hbm.xml file i can hold the control key and click on
jp.go.mhlw.vaccine.draft.PurchasedTestId
And it immediately jumps to PurchasedTestId.java file with same package name.Obviously the PurchasedTestId class is in my classpath.I've been searching alot for 2 days but i could not solve my problem.Please help me figure out what it is.I am so tired
Please help me.
You don't have to specify the class of the composite-id in the hbm.xml file; you have to set the name of the property in your PurchasedTestttt class.
E.g. it has to look like:
Class PurchasedTestttt:
public class PurchasedTestttt {
PurchasedTestId purchasedTestId;
public PurchasedTestId getPurchasedTestId() {
return purchasedTestId;
}
public void setPurchasedTestId(PurchasedTestId purchasedTestId) {
this.purchasedTestId = purchasedTestId;
}
....
}
*.hbm.xml:
<class name=”entities.PurchasedTestttt”>
<composite-id name=”purchasedTestId”>
<key-property name=”testId” column=”TEST_ID” />
<key-property name=”customerId” column=”CUSTOMER_ID” />
</composite-id>
...
</class>
It is important that the class you use for the composite-id has properties with the same name as specified in *.hbm.xml, but Hibernate does not need to know the class you used for that.
I have a class called WebAsset:
public class WebAsset {
private Long id;
private String url;
private int status;
//more fields that are not relevent
}
I need to be able to show relationships between WebAsset, so I created a table for the relationship and a composite key class.
public class WebAssetReferencePK {
private Long sourceAssetId;
private Long targetAssetId;
}
public class WebAssetReference {
private WebAssetReferencePK wpk;
private Long updateTime;
}
We are forced to use an older version of Hibernate so we need to use xml files instead of annotaions. Here is the mapping for the reference class:
<class name="ca.gc.cra.www.crawler.valueobject.WebAssetReference" table="webassetreference">
<composite-id name="webAssetReferencePK" class="ca.gc.cra.www.crawler.valueobject.WebAssetReferencePK">
<key-property name="sourceAsset" type="java.lang.Long" column="sourceAssetId" />
<key-property name="targetAsset" type="java.lang.Long" column="targetAssetId" />
</composite-id>
<property name="updateTime" type="java.lang.Long" column="updatetime" not-null="true" />
</class>
In the composite key I get what I expect in the database with 2 ids related to each other. But when I try to query with HQL or Criteria it doesn't work since there is no direct relation between the PK class and WebAsset and I need to be able to do a join between WebAsset and WebAssetReference. If I try to change the composite key types from java.lang.Long to WebAsset then hibernate stores the whole object in the WebAssetReference table instead of just the ids.
An example of what I am trying to do is if I have a sourceAssetId I want to return all the targetAssetIds with the same source, but I don't want the ids themselves I want the WebAsset that is the primary key for each targetAssetId.
I have been searching around for the answer but every example I can find are just simple examples that don't relate.
Update 1: With continued searching I finally found the answer. Instead of key-property I need to use key-many-to-one. I haven't tried a join yet but everything else looks right so this should be the answer.
Update 2: Can't get the query to work with HQL. Here is th SQL of what I am trying to do:
select * from webasset as wa join webassetreference as war on war.targetassetid=wa.webasset_id where war.sourceassetid=?
Here is the HQL that is not working:
FROM WebAsset JOIN WebAssetReference WebAssetReference.WebAssetReferencePK.targetAsset=WebAsset WHERE WebAssetReference.WebAssetReferencePK.sourceAsset = :sourceAsset
I get the following error with HQL: ERROR - line 1:89: unexpected token: .
I'll keep trying but I can't seem to figure out the HQL.
I discovered how to do this. In the case I have above it will not work since I have 2 columns joining to the same table. However if I use the same WebAsset class above and instead use this class:
public class TreeNode implements Comparable<TreeNode>{
private String nodeUrl;
private Long id;
private Boolean folder;
private transient WebAsset nodeAsset = null;
}
With this .hbm.xml file:
<class name="ca.gc.cra.www.crawler.valueobject.TreeNode" table="TreeNode">
<id name="id" type="java.lang.Long" column="treenode_id" >
<generator class="identity"/>
</id>
<many-to-one name="nodeAsset" class="ca.gc.cra.www.crawler.valueobject.WebAsset" column="nodeAsset_id" lazy="false" not-null="false" cascade="none" unique="true" />
<property name="folder" type="java.lang.Boolean" column="folder" not-null="true" />
<property name="nodeUrl" length="512" type="java.lang.String" column="nodeUrl" not-null="true" />
<set name="children" table="TreeNode" inverse="false" lazy="true" >
<key column="parentnode_id"/>
<one-to-many class="ca.gc.cra.www.crawler.valueobject.TreeNode" />
</set>
</class>
You can then use this code to retrieve the join:
Session session = HibernateUtil.getSession();
try {
String hql = "FROM TreeNode tn JOIN tn.nodeAsset WHERE tn.id=5";
Query query = session.createQuery(hql);
List result = query.list();
System.out.println("done");
} catch (HibernateException e) {
e.printStackTrace();
throw new Exception("Query failed", e);
} finally {
session.flush();
session.close();
}
Hibernate can then perform the join correctly. The result will be a List containing an Object array for each entry. The Object contains the 2 classes that are part of the join. You have to cast the Object with (Object[]) to access the elements and then cast each on to the appropriate class.
I would recommend against this approach because Hibernate will attempt to load all connected classes as well. With the example above I was getting 1 row from TreeNode yet it generated 19 select statements. I even attempted to set the connected classes to lazy load and it still generated all the selects.
I have three tables similar to these:
vehicles
- id1
- id2
- vehicle_type_id
- vehicle_detail_id
- primary key(id1, id2)
buses
- id
...
cars
- id
...
vehicleTypeId decides the type of the vehicle and also from which table the vehicleDetails are to be fetched. Join is to be taken on vehicleDetailId of vehicle and id of a particular vehicleType.
I created classes this way:
class Vehicle{
VehiclePk pk;
Long vehicleTypeId;
Long vehicleDetailId;
}
class Bus extends Vehicle{
Long id;
}
class Car extends Vehicle{
Long id;
}
class VehiclePk {
private Long id1;
private Long id2;
#Override
public boolean equals(Object obj) {
if(obj != null && obj instanceof VehiclePk) {
VehiclePk p = (VehiclePk)obj;
return id1.equals(p.id1) && id2.equals(p.id2);
}
return false;
}
#Override
public int hashCode() {
return (id1 + id2).hashCode();
}
}
I tried combining and elements in the hibernate mapping file, using discriminator:
<?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 schema="test_db">
<class name="Vehicle" table="vehicles" discriminator-value="0">
<composite-id name="pk" class="VehiclePK">
<key-property name="id1" column="id1" type="long"/>
<key-property name="id2" column="id2" type="long"/>
</composite-id>
<discriminator column="vehicle_type_id" type="long"/>
<property name="vehicleDetailId" column="vehicle_detail_id" type="long"/>
<subclass name="Bus" discriminator-value="1">
<join table="vehicles" >
<key column="vehicle_detail_id" />
...
</join>
</subclass>
<subclass name="Car" discriminator-value="2">
<join table="vehicles" >
<key column="vehicle_detail_id" />
...
</join>
</subclass>
</class>
There is something wrong with the mapping file, as the DB is not getting initialized. Please let me know if I have missed something. Thanks.
UPDATE : It gives ArrayIndexOutOfBoundsException: 1
Stacktrace :
...
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1206)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1026)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4421)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4734)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1385)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:306)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1389)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1653)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1662)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1642)
at java.lang.Thread.run(Thread.java:662)
This is a typical error message when the number of columns is not correct. In this case, you have only one primary key column in your join. Joins are primary-key related tables, so they need to have the same primary keys. In your case, the vehicles have two ids, while the buses and cars have only one.
The join element specifies a new table with the key column as both primary key and foreign key.
Consider making it a many-to-one which has a different type per subclass. (Instead of the join).
It would also map to a one-to-any property.