Get annotation parameter with IntelliJ IDEA structural search - java

I'm trying to generate named queries for JPA entities using table name specified in #Table annotation with structural search and replace.
So to start I'm trying the following template:
#Table($param$ = $value$)
public class $clazz$
I have many classes like:
#Table(name = "Some Table")
public class SomeClass
and if I replace with the same template, it correctly grabs that $param$ is name, $clazz$ is correct class name, but $value$ is empty.
I'm using IDEA 12 build 128.101
What am I doing wrong? Thank you.

I think this issue was already reported a long time ago, but no one seems to care about it. Try voting up the ticket in youtrack.

Related

How to dynamically add Entity in Hibernate?

I'm a java developer. I'm using spring 4.0.1 and hibernate 4.2.21. I have a class as follow:
#Entity
#Inheritance(...)
public abstract class Feature{
#Id
#GeneratedValue
protected Long id;
...
}
Now I have some many class as follow:
Label.java class:
#Entity
public class Label extends Feature{
protected String str;
...
}
Point.java class:
#Entity
public class Point extends Feature{
protected Integer intg;
...
}
I have more than 20 Entity class that extends from Feature class. Is there any way to add dynamically this classes(such as Label and Point) to the project without writing hard code?
update:
For example, Hibernate get data from a database and then according this data, create models.
Is it possible?
How do I do?
I think its not a good database design that needs to be changed dynamically. It sounds verbose and not consistent. Observe your domain again and try to design a proper entity relationships that wouldnt be changed over run time.
You can try to collect the needed data to build the model and generate a hibernate hbm.xml file for each entity (is xml format and easy to generate with java after reading the data needed as you describe in your update)
After that, you can create programmatically a hibernate configuration object following this http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html#configuration-programmatic
I Think with that approach you can achieve what you want if I understand well your question.
I think you want to generate your entity class at runtime instead of that you have to write your java file and compile it and so on.
If this is your requirement you can use a byte code generator like javassist to generate and annotate your class file at runtime. Then you can persist it to your table using JPA, Hibernate and any other ORM framework.
As I understand you need to develop a tool, collects table names that have one-to-one relationship with Feature table.
My suggestion is like that (tested with Oracle):
1) From your DB, get tables metadata who is referancing your Feature table.
Below will print your Label, Point, etc tables who has foreign key relation to your table.If you want to only generate a subset (irrelevant tables might has this relationship too) may be you put a common foreign key column name and filter out non-related tables with a help of such marking.
Connection connection = jdbcTemplate.getDataSource().getConnection();
DatabaseMetaData metaData = connection.getMetaData();
ResultSet exportedKeys = metaData.getExportedKeys(connection.getCatalog(), "<your_schema_name>", "FEATURE");
while (exportedKeys.next()){
String fkTableName = exportedKeys.getString("FKTABLE_NAME");
String fkColumnName = exportedKeys.getString("FKCOLUMN_NAME");
System.out.println("[fkTableName:" + fkTableName + "], [fkColumnName" + fkColumnName + "]");
}
exportedKeys.close();
2) For the tables you collected above, for each table of our concern, get table metadata for the types and columns.
ResultSet columns = metaData.getColumns(connection.getCatalog(), "<your_schema_name>", "<your_table_name>", null);
while (columns.next()){
String columnName = columns.getString("COLUMN_NAME");
String typeName = columns.getString("TYPE_NAME");
System.out.println("[columnName:" + columnName + "], [typeName" + typeName + "]");
}
columns.close();
3) According to result from 2 generate your Java classes. With fields, getter setters, annotations etc. Then copy them into your source directory. You know the rest :)
Hope this is helpful.
I think you can use Hibernate Reverse Engineering to generate Entity for all the database tables. Please refer this Link. That will explained step by step process to generate entity from database using hibernate reverse engineering.
Do not repeat yourself.
If you really need those classes use an IDE (like eclipse) to generate the classes. Or use generics and inheritance to create only one class that is capable of storing Strings as well as Integers.
But if you do not actually need classes, generate SQL (not JPQL nor HQL) and to store the data in java.util.Map and similar data structures.
Classes are good for:
type safety
combining logic (methods) with data (fields)
describing relationships
In your case you might only need:
store structured data at runtime.
I think you could do this with eclipse, but the classes had to be modified more or less to preserve the inheritance hierarchy.
Righ click on the project name and select Properties
Use project facets if project facets not enabled
Click the JPA if it's not selected, then click OK to close the project properties window.
After enabling JPA in project properties, now right click you eclipse project name again, you should see a new context menu item JPA tools appears. Choose Generate Entities from tables
Select a database connection to let Eclipse get the tables used to generated
class from.
Here is how to setup db in eclipse
It's better to create the entities in a dummy project using the above method and copy the Entity classes to the real project.
Eclipse's Class refactoring may be used to preserve the inheritance hierarchy that you want.
Hope this helps.

Hibernate #Synchronize does not seem to be working

I have 2 Entitites, one maps to a database table, the other to a database view.
The data of the view depends on the table.
#javax.persistence.Table(name = "BOOKING_INFO", schema = "BOOKING")
#Entity
public class BookingInfo extends AbstractBooking {
#javax.persistence.Table(name = "BOOKING_VIEW", schema = "BOOKING")
#Entity
#Immutable
public class BookingView extends AbstractBooking {
This works fine in most cases, however when we write (insert or update) the Booking entity and then do queries (in my case a count) on the BookingView entity, we get stale data.
Why this happens is clear to me (hibernate caching, it only flushes when it detects that a select needs some data flushed).
So if I would do a query on the Booking entity, it would trigger a flush.
I have found the #Synchronize Annotation in Hibernate which sounds like it should fix this problem, like this:
#javax.persistence.Table(name = "BOOKING_VIEW", schema = "BOOKING")
#Entity
#Immutable
#Synchronize("BOOKING.BOOKING_INFO")
public class BookingView extends AbstractBooking {
However this does not make any difference (flush only happens at the end of the transaction). Also the documentation I have found about this annotation is quite lacking and not very helpful.
EDIT: I also tried #Synchronize("BOOKING_INFO") (without the schema name, and also lowercase, but that made no difference)
The docs say that it is mostly used with #Subselect but it is not a must (I don't want that).
Has anyone ever successfully used this annotation?
Is there any other way to handle database views in Hibernate?
Am I missing something else?
Thanks to a colleague we were able to debug and fix this, the problem was that our Hibernate naming-strategy lowercased our table-names, so the correct annotaiton is:
#Synchronize("BOOKING.booking_info")
How to debug this:
set breakpoints in Hibernates ActionQueue class in the areTablesToBeUpdated methods.
There we saw that it compared "BOOKING.BOOKING_VIEW" to "BOOKING.booking_view".
We think this is a bug in hibernate because it should either apply the naming-strategies also to the values from #Synchronize or compare these case-insensitive (which could theoretically lead to too many flushes if you have a crazy database which uses tables with the same name only differentiated by casing).
Created a Hibernate issue: https://hibernate.atlassian.net/browse/HHH-10002

Spring Mongo Exception - Customizing field name for id property not allowed! Custom name will not be considered

I have been using Spring-Data-Mongo for a while now on a project without issues. In the last POM update, I started seeing the following exception in the log file:
WARN : 04 Aug 2014 13:55:24
org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty
- Customizing field name for id property not allowed! Custom name will not be considered!
It does not provide any clue as to where this issue arises so we are clueless. It is repeated several times as calls to the app are made. We did find the origin of this here: https://github.com/spring-projects/spring-data-mongodb/blob/11417144bd3574c35af06fde3a3c2e56a1dd5890/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java#L85
Any ideas?
Edit:
Added example class for those interested:
#Document(collection="Account")
public class Account {
....
#Id
private String id = null;
....
}
I listened to the nice comments above and put a breakpoint on . I quickly found out that one of my classes was using the following:
#Id
private String Id;
Note the Id instead of id. Once changed, the warning disapearind.
I fully support the suggestion to have spring-data provide a proper report rather than simply a meaningless warning.
My thought is that you are trying to use #Id with #Field on the same field. This is not allowed since the id field in Mongo must be called _id. Anything further is hard to tell since you didn't post your code.

org.hibernate.AnnotationException: #OneToOne or #ManyToOne on <entity> references an unknown entity

I am receiving the following Hibernate Exception:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on cz.rohan.dusps.model.Switchport.konfiguracniTemplateAccess references an unknown entity: cz.rohan.dusps.model.KonfiguracniTemplate
org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:103)
org.hibernate.cfg.AnnotationConfiguration.processEndOfQueue(AnnotationConfiguration.java:541)
org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:523)
org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:380)
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1377)
org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
cz.rohan.dusps.helper.SessionFactoryHelper.initFactory(SessionFactoryHelper.java:122)
cz.rohan.dusps.helper.SessionFactoryHelper.getSessionFactory(SessionFactoryHelper.java:134)
cz.rohan.dusps.filter.HistorieZmenFilter.doFilter(HistorieZmenFilter.java:102)
cz.rohan.dusps.filter.CharsetFilter.doFilter(CharsetFilter.java:41)
after ~20 hours spent on the problem with various people, having read every possible blog or forum, I am really getting desperate here.
This is a mid-sized project. I should mention the database is Postgres 9.1 and we generate the DB using a modelling tool. Hibernate connects to the database but does not generate it.
I have created a new entity in the database, it's called "KonfiguracniTemplate" (configuration template). I have created the model, controller, form, validators, .jsp's, all basically copied 1:1 from an existing entity of a similar nature. I can now work with KonfiguracniTemplate, CRUD is fully working.
The problem comes when I reference this KonfiguracniTemplate from the entity called Switchport. In the DB there is a relation between the two:
Switchport 1:1 ... 0:N KonfiguracniTemplate (switchport always references a KonfiguracniTemplate; a KonfiguracniTemplate MAY BE referenced zero or more times)
Switchport has FK konfiguracniTemplateAccess_id for this relation.
In .../model/Switchport.java the relation is mapped just like all other relations that are working:
#ManyToOne
#JoinColumn(nullable = false)
private KonfiguracniTemplate konfiguracniTemplateAccess;
I have tried various forms:
#ManyToOne
#JoinColumn(name="konfiguracnitemplateaccess_id", nullable = false)
private KonfiguracniTemplate konfiguracniTemplateAccess;
or
#ManyToOne(targetEntity=KonfiguracniTemplate.class)
#JoinColumn(name="konfiguracnitemplateaccess_id", nullable = false)
private KonfiguracniTemplate konfiguracniTemplateAccess;
I have also checked:
both entities are in the same package
they are both annotated "#Entity" using "import javax.persistence.Entity;"
the build produces no error/warning messages
as long as the reference in Switchport is commented out, everything is fine
No matter what I try I cannot get rid of the "references an unknown entity" exception. Can somebody please share an idea what is happening or maybe how to debug the issue? The stacktrace at the top of the post is all I get in the logs.
All input is greatly appreciated!
Just add the class Team to the "hibernate-cfg.xml" file, because Hibernate doesn't identify without adding into it.
Possible Solutions:
1) Ensure that the entity has been appropriately referenced in hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
...
<mapping class="com.project.entitytwo.model.EntityTwo"/>
...
</session-factory>
2) Ensure that #Entity has been specified at the class-level ( at the top of the class )
#Entity
#Table( name="ENTITY_TWO" )
public class EntityTwo extends AnyClass
{
...
I just had this problem, with entity a referencing entity b. Both entities were located in a common JAR outside of the web project I was working on; a was declared in persistence.xml but b wasn't. I put b in a <class> tag in persistence.xml and it worked!
I ran into this problem when using Spring and not using the hibernate.cfg.xml file. It was solved by adding the fully qualified package name of the Model class to the setPackagesToScan method of LocalSessionFactoryBean class.
Finally got the solution from another developer on the team!
The classes need to be imported before the SessionFactory object is created. Here the import for the new class was missing, so it was unknown to the SessionFactory object.
Anyway, thanks everyone for your hints!
There is one more chance of getting such exception; when you don't mention your mapping class in hibernate.cfg.xml file.
As mentioned above.
I had same exception... I just forget add annotation (#Entity, and #Table) on MASTER class(class with Primary key)
so solution is double check every annotation in your entities , I mean not only #ManyToOne and #OneToMany like i did.
if your two entity in diffrent project,you can scan KonfiguracniTemplate's package in other project.you can do like this in spring boot
#EntityScan({"com.thispackage.entity","com.KonfiguracniTemplatepackage.entity"})
I'll give you a solution that should work for the same error with Spring Boot. This has less to do with the original question, but today, people would probably look for this answer instead because noone uses XML configuration today anymore.
I suffered the same problem and found the solution on this website: https://www.programmersought.com/article/1617314625/
He even describes this very question he would have looked up, but then I'm asking myself: why didn't he answered here after finding the solution? LOL
His own words:
In the Spring Boot project, the default scan package is the package where the main method is located, that is, only the entity classes in the same package as the main method will be discovered. This way you can understand why User is not found: because User is an entity class in another module. Spring Boot does not scan other packages at all;
Configure the #SpringBootApplication annotation on the main method that launches the application, telling Spring Boot that those packages need to be scanned: #SpringBootApplication(scanBasePackages = {“com.xiaomo.*”})
Then, User can be found.
So you basically reconfigure SpringBoot to scan more packages to include the other ones.
My personal addition: you could also move your packages into the package where the starter is located or move the starter a package up (that's what I did).

Why Hibernates ignores the name attribute of the #Column annotation?

Using Hibernate 3.3.1 and Hibernate Annotations 3.4, the database is DB2/400 V6R1, running that on WebSphere 7.0.0.9
I have the following class
#Entity
public class Ciinvhd implements Serializable {
#Id
private String ihinse;
#Id
#Column(name="IHINV#")
private BigDecimal ihinv;
....
}
For reasons I can't figure, Hibernate ignores the specified column name and uses 'ihinv' to generate the SQL:
select
ciinvhd0_.ihinse as ihinse13_,
ciinvhd0_.ihinv as ihinv13_,
...
Which of course gives me the following error:
Column IHINV not in table CIINVHD
Edit: I switched the log level of hibernate to DEBUG, and I see that it does not process the column annotation for that field. Tried several random things it just doesn't work.
Did anyone had this problem before? I have other entities that are very alike in the way that they are using # in their database field names and that are part of the PK and I don't have this problem with them.
You could try some kind of quoting:
For example:
#Column(name="`IHINV#`")
or
#Column(name="'IHINV#'")
Another option would be to dig in to source code Hibernate dialect for DB2 and see if it contains anything helpful.
Of course, the easiest way would be to remove the hash from column name if possible.
I suspect that the problem is the hash in the column name. A similar question on the hibernate forums suggests that backticks can be useful here.

Categories

Resources