How to get the postgresql column names in java springboot - java

I'm trying to get the postgresql table column name. I've tried using information_schema but it doesn't work on my java mvc project. What should I do ?
This is actually my first question on StackOverflow, so I'm sorry if my question is difficult to understand. Thank you!
public interface MyFileRepository extends JpaRepository<MyEntityModel, Long> {
#Query("select column_name,data_type from information_schema.columns where table_name = 'MyEntityModel';")
List<MyEntityModel> myList();
}

About schema. You can set default schema by two ways:
Put it to the properties(or .yml file) spring.datasource.schema = #your schema name
Put it in your entity model #Table(schema = "SCHEMA_NAME")
About getting information about table you can look this one open question:
Is there any Simplest way to get Table metadata (column name list) information, in Spring Data JPA ? which could I use on universal database

Related

Get Data from 2 tables in spring boot jpa

I have one table which has all the api audit information - Table name : api_audit
I have one table which has extra information about every api call - Table name : api_audit_info
Inside api_audit I have primary key as "transaction_id".
I want all the data from api_audit table and some data from api_audit_info table.
I have written a custom query like -
#Query(select c from ApiAudit c INNER JOIN ApiAudiInfo t ON c.transactionId = t.msgId)
But the issue is that the result type that I am getting this way contains only ApiAudit type data.
What shall I do to get data from both the tables. Please help.
Note: I am using JpaRepository as I need paginated data.
I am fairly new to Spring boot and JPA so not sure exactly which direction to look to.
Whenever I need to join data from more than 1 table, I am using Jdbi.
Here you have the official documentation:
Remember to include the required dependencies and configure a bean for Jdbi in your project.
Then I create a repository class, POJO and query with all of the information which I need. For example:
select c.transaction_id as transactionId, t.name as name from ApiAudit c INNER JOIN ApiAudiInfo t ON c.transactionId = t.msgId
Here you have some code samples from official documentation
After you map your data to POJO, you can use
public PageImpl(List<T> content, Pageable pageable, long total)
to return paginated data.
There is a big chance that there is a better solution, but this works for me every time.

Dynamic Table name in Cassandra Pojo Sink Flink

I am a newbie to Apache Flink. I am using Pojo Sink to load the data into Cassandra. Right now, I am specifying table and keyspace names with the help of #Table annotation.
Now, I want to pass table name and keyspace name dynamically on run time so that I can load data into tables specified by user. Is there any way to achieve this?
#Table is a CQL annotation that defines which table this class entity maps to. AFAIK, currently there is no way to make it dynamically mapped to any table at run time, because it would infer to the class name if the name is not specified, i.e.
#Table
public class MyTable {...}
infers a table 'mytable'
#Table(table = "another_table")
public class AnotherTable
infers the table 'another_table'

More than one table found in namespace (, ) - SchemaExtractionException

I have been facing this weird exception while trying to persist some values into a table using Hibernate in a Java application. However this exception occurs only for one particular table/entity for rest of the tables i am able to perform crud operations via Hibernate.
Please find below the Stacktrace and let me know if this is anyway related to java code is or its a database design error.
2016-04-28 11:52:34 ERROR XXXXXDao:44 - Failed to create sessionFactory object.org.hibernate.tool.schema.extract.spi.SchemaExtractionException: More than one table found in namespace (, ) : YYYYYYY
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.XX.dao.XXXXXXXDao.main(XXXXXXXXDao.java:45)
Caused by: org.hibernate.tool.schema.extract.spi.SchemaExtractionException: More than one table found in namespace (, ) : YYYYYYY
at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.processGetTableResults(InformationExtractorJdbcDatabaseMetaDataImpl.java:381)
at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.getTable(InformationExtractorJdbcDatabaseMetaDataImpl.java:279)
at org.hibernate.tool.schema.internal.exec.ImprovedDatabaseInformationImpl.getTableInformation(ImprovedDatabaseInformationImpl.java:109)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.performMigration(SchemaMigratorImpl.java:252)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:137)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:110)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:176)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:458)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at com.xx.dao.zzzzzzzzzzzzDAOFactory.configureSessionFactory(zzzzzzzDAOFactory.java:43)
at com.xx.dao.zzzzzzzzzzzzDAOFactory.buildSessionFactory(zzzzzzzzzDAOFactory.java:27)
at com.xx.dao.XXXXXXXXDao.main(XXXXXXXXDao.java:41)
Thanks in advance for your help
I have had the same problem and was able to dig down to the code to find out the cause, at least in my case. I don't know whether it will be the same issue for you but this may be helpful.
From your stack trace I can see you have the hibernate.hbm2ddl.auto set to upgrade the schema. As part of this, it is trying to look up the metadata for all the tables hibernate knows about and for one of them getting an ambiguous answer because the metadata query is returning more than a single row of table or view metadata.
In my case this was caused by our naming convention for tables. We had a table called (say) "AAA_BBB" for which this was going wrong. Now the use of an underscore in the table name is perfectly acceptable as far as I am aware and is quite common practice. However the underscore is also the SQL wildcard for a single character; looking in the code for the database metadata I can see it is doing a "WHERE table_name LIKE ..." in DatabaseMetaData.getTables(...) method, which is what hibernate is using here.
Now, in my schema I also had a second table called "AAA1BBB" and hence both of these matched the metadata lookup and so it returned a metadata row for each of these tables. The hibernate method is written to just fall down if the result set from the table metadata lookup returns more than one row. I would guess it should examine the available row(s) and find if there is one which is an exact match with the specified table name.
I tested this for both Oracle and MySQL with the same result.
Seems the property hibernate.hbm2ddl.auto set to update is causing the issue here. Try removing it from your hibernate config xml.
This will work:
Check your database schema/s and your database user privileges;
Hibernate update mechanism may fail with this exception if there is a another database schema/user with the same table name, and the db user has the sufficient privileges to view this table.
So in your case, the table 'YYYYYYY' may be found in more than one database user/schema, and your db user has 'DBA' privileges.
To solve this you can either find and delete the ambiguous table or remove the user's redundant privileges.
Another situation may be occurred except whatever dear RichB has been stated.
in ORACLE every user has separate schema ,
Therefore probably there is tow tables with the same name in two different schemes
then you should specify your default schema in persistence.xml with below property
<property name="hibernate.default_schema" value="username"/>
Use catalog value with #Table, i.e.:
#Entity
#Table(**catalog = "MY_DB_USER"**, name = "LOOKUP")
public class Lookup implements Serializable {
}
I don't have this error now.
Hope this work.
We had a Spring Data / JPA application and this error started happening after upgrading to Postgres 10.6 (from 10).
Our solution was as follows, in our JPA configuration class: note the new commented line,
props.put("hibernate.hbm2ddl.auto", "none"); //POSTGRES 10 --> 10.6 migration
Class:
#Configuration
#EnableJpaRepositories(basePackages = "app.dao")
#ComponentScan(basePackages = { "app.service" })
#EnableTransactionManagement
public class JpaConfig {
#Autowired
DataSource dataSource;
#Bean
public Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<String, Object>();
props.put("hibernate.dialect", PostgreSQL95Dialect.class.getName());
props.put("hibernate.hbm2ddl.auto", "none"); //POSTGRES 10 --> 10.6 migration.
return props;
}
So after having the same issue, it turns out that I needed to update my OJDBC driver from ojdbc6 to ojdbc8. Hopefully this helps.
I have same issue with such configuration
#Entity
#Table(name = "NOTIFICATION")
public class Notification {
...
}
issue was resolved for me when I moved table name from #Table to #Entity
#Entity(name = "NOTIFICATION")
#Table
public class Notification {
...
}
Simply, if u are using two schemas then u will get this error. To resolve this error u can use these steps :
1. You need to delete extra schema.
2. Or u can define default schemas or that schema are u using.
spring.jpa.properties.hibernate.default_schema=nameOfSchema
and
jdbc:postgresql://localhost:5432/databaseName?currentSchema=nameOfSchema
I also came across this issue. Here is my solution:
the error:
https://gist.github.com/wencheng1994
I solve that. It mainly because the db account has a higher authority. I set the "hibernate.hbm2ddl.auto=update", So when hbm2ddl works, it tried to find all exists shcema I defied. But there is two schema exist the table with the same name. then the db account can find that. so it found "more than one table in the namespace"
All I need to do is to make the db account lower authority so that it can not find table in other schema. (one shcema relation one db account).

Hibernate returns only one result (After changing table names)

I am using hibernate retrieve results from my MySQL database into my Java project. Recently, I had a lot of redundant data and had to manually clean up the database by copying the required data into new tables and then renaming the newly created table to old table.
But, now querying the database with hibernate gives only one row as the result. I have manually checked the database and there are several different rows in the database. My query to Hibernate is something like this:
Criteria c = session.createCriteria(UserDto.class);
c.setMaxResults(100);
List<UserDto> users = c.list();
users contains 100 elements but all are the same.
The mapping of userDto is here.
Any idea what is happening here?
If your UserDto class has ToMany relations, then this is quite possible that outer join on them results in many records which all contain one and the same user data. You should use
session.createCriteria(UserDto.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Double-check your mapping of the UserDto class to the database.
My guess is that you don't have it mapped to the table that you think you do.
As Sebastien mentioned, setting hibernate.show.sql to true should make this obvious.
Did you deleted the old tables? And in the configuration file what is the value for "hibernate.hbm2ddl.auto"?
I think the reason is these records have same id, so Hibernate treat them as the same record. You can check it.
I had same problem. In my case, the problem detected when I created a table in MySQL manually and I tried to read data from that table using hibernate and a dto class. After checking my dto class fields and database table, I figured out that there is a difference between table column named "id" and the class field which named dbId. The code was something like this:
#Id
#GeneratedValue
#Column(name="db_id", unique = true)
private long dbId;
So I edited the name and changed the code:
#Id
#GeneratedValue
#Column(name="id", unique = true)
private long dbId;
Which "id" was the correct name of databse table column and the problem has been solved.

JPA - Setting entity class property from calculated column?

I'm just getting to grips with JPA in a simple Java web app running on Glassfish 3 (Persistence provider is EclipseLink). So far, I'm really liking it (bugs in netbeans/glassfish interaction aside) but there's a thing that I want to be able to do that I'm not sure how to do.
I've got an entity class (Article) that's mapped to a database table (article). I'm trying to do a query on the database that returns a calculated column, but I can't figure out how to set up a property of the Article class so that the property gets filled by the column value when I call the query.
If I do a regular "select id,title,body from article" query, I get a list of Article objects fine, with the id, title and body properties filled. This works fine.
However, if I do the below:
Query q = em.createNativeQuery("select id,title,shorttitle,datestamp,body,true as published, ts_headline(body,q,'ShortWord=0') as headline, type from articles,to_tsquery('english',?) as q where idxfti ## q order by ts_rank(idxfti,q) desc",Article.class);
(this is a fulltext search using tsearch2 on Postgres - it's a db-specific function, so I'm using a NativeQuery)
You can see I'm fetching a calculated column, called headline. How do I add a headline property to my Article class so that it gets populated by this query?
So far, I've tried setting it to be #Transient, but that just ends up with it being null all the time.
There are probably no good ways to do it, only manually:
Object[] r = (Object[]) em.createNativeQuery(
"select id,title,shorttitle,datestamp,body,true as published, ts_headline(body,q,'ShortWord=0') as headline, type from articles,to_tsquery('english',?) as q where idxfti ## q order by ts_rank(idxfti,q) desc","ArticleWithHeadline")
.setParameter(...).getSingleResult();
Article a = (Article) r[0];
a.setHeadline((String) r[1]);
-
#Entity
#SqlResultSetMapping(
name = "ArticleWithHeadline",
entities = #EntityResult(entityClass = Article.class),
columns = #ColumnResult(name = "HEADLINE"))
public class Article {
#Transient
private String headline;
...
}
AFAIK, JPA doesn't offer standardized support for calculated attributes. With Hibernate, one would use a Formula but EclipseLink doesn't have a direct equivalent. James Sutherland made some suggestions in Re: Virtual columns (#Formula of Hibernate) though:
There is no direct equivalent (please
log an enhancement), but depending on
what you want to do, there are ways to
accomplish the same thing.
EclipseLink defines a
TransformationMapping which can map a
computed value from multiple field
values, or access the database.
You can override the SQL for any CRUD
operation for a class using its
descriptor's DescriptorQueryManager.
You could define a VIEW on your
database that performs the function
and map your Entity to the view
instead of the table.
You can also perform minor
translations using Converters or
property get/set methods.
Also have a look at the enhancement request that has a solution using a DescriptorEventListener in the comments.
All this is non standard JPA of course.

Categories

Resources