Cannot override Persistence Unit keyspace with annotation
I am attempting to work with two entities in different keyspaces on the same Cassandra cluster. Since both keyspaces I intend to work with are in the same cluster (and using the Datastax driver by itself allows you to work with multiple keyspaces on the same connection), I figured on being able to get away with using only a single persistence unit, naming the first keyspace property in it since that's required:
kundera.keyspace=keyspace_one
In my entities, I explicitly indicate what keyspace the tables are on:
@Table(name="table_one",schema="keyspace_one@cassandra_pu") @Table(name="table_two",schema="keyspace_two@cassandra_pu")
However, with kundera.ddl.auto.prepare=validate, I find that validation fails because Kundera attempts to work with keyspace_one.table_two, which does not exist.
To figure out why, I went spluenking in com.impetus.kundera.metadata.MetadataUtils and found this:
public static void setSchemaAndPersistenceUnit(EntityMetadata m, String schemaStr, Map puProperties)
{
if (schemaStr.indexOf(Constants.SCHEMA_PERSISTENCE_UNIT_SEPARATOR) > 0) //true in my case
{
String schemaName = null;
if (puProperties != null) //true in my case
{
schemaName = (String) puProperties.get(PersistenceProperties.KUNDERA_KEYSPACE);
}
if (schemaName == null) //false due to previous if block
{
schemaName = schemaStr.substring(0, schemaStr.indexOf(Constants.SCHEMA_PERSISTENCE_UNIT_SEPARATOR));
}
m.setSchema(schemaName);
m.setPersistenceUnit(schemaStr.substring(
schemaStr.indexOf(Constants.SCHEMA_PERSISTENCE_UNIT_SEPARATOR) + 1, schemaStr.length()));
}
else
{
m.setSchema(StringUtils.isBlank(schemaStr) ? null : schemaStr);
}
}
Reading this, it looks like the kundera.keyspace value will always take precedence over the annotated keyspace value, which is not desired behavior for my use case, seeing as I wish to override the persistence keyspace for certain entities. As it stands, I am forced to make a new persistence unit for each keyspace I wish to work with.
@bmckenzie042188
As of now, Kundera maps each keyspace with one persistence unit. This is supposed to be this way for easy understanding of the structure. We would consider changing it depending on its importance and requirement.
-Karthik
That makes sense. However, consider the following situation:
kundera.keyspace=keyspace_one
Entity:
@Table(name="table_one",schema="arbitrary_name_that_doesnt_mean_a_thing@cassandra_pu")
Following the code, schema for table_one is set to kundera.keyspace (keyspace_one), and its persistence unit is set to cassandra_pu. As long as the string contains @ and @ is not the first character in the string, anything before the @ is completely meaningless, which took me going through source code to understand. It may make the structure easier to understand, but it makes the schema attribute on the Table annotation a bit obtuse.
Playing with this, this behavior actually worked out for me, as I can externalize my keyspace details and set kundera.keyspace from loaded java properties when I instantiate the EnitityManagerFactories. I guess my only complaint here is that I did not find any documentation indicating that if kundera.keyspace is defined, the schema part of the pattern schema@persistence_unit is completely ignored.
Right now I have two Enitities on two different pu's, each pointing to a different schema:
@Table(name="table_one",schema="schema@cassandra_pu_one")
@Table(name="table_two",schema="schema@cassandra_pu_two")
The schema@ part of these schema names do nothing except offset the @ enough to cause the setSchemaAndPersistenceUnit method to branch in the way I'd like, since I fed the kundera.keyspace property to both of my Entity ManagerFactories independently.
Hi,
I have the same issue and, moreover, I would like to reuse the same EntityManagerFactory for more than one EntityManager, since Kundera supports more than one PU in the config file. What I've found is that Kundera does not use the kunder.keyspace property when instantiating the EntityManagers. What I've also found is that Kundera does not enjoy having 2 PUs of the same type (Cassandra, in my case). I've changed Kundera's code to support this but I'm still testing it. If I reach any conclusion, I'll try to submit it for appreciation by the team.
Regards
Hi @si24803,
Kundera does not enjoy having 2 PUs of the same type
What do you mean by this?
Also, kundera.keyspace should be used when instantiating EntityManagerFactory and not EntityManager. What are you trying to achieve through this?
-Karthik
Hi @karthikprasad13
Sorry @karthikprasad13 , I was wrong when I said that
Kundera does not enjoy having 2 PUs of the same type
It most certainly does as this was the technique I was using and thought it introduced an unnecessary slowness. I wanted to tie both keyspaces toghether in one persistence unit.
What I'm trying to achieve is to use the same EMF for two different keyspaces in Cassandra. I thought I would be able to do it by having one persistence unit in persistence.xml with all my entity classes but, unfortunately, I realised that does not work because the kundera.keyspace property is not passed along to the EntityManagers on EMF.createEntityManager(SynchronizationType, Map). Since the schema annotation in the entity classes does not work, I though I could do it this way. I was wrong. But I think I may have found a solution but I'm still testing it.
Regards