Support for Spring Data JPA multiple dataasource configuration for implicit column names from model class in accordance with table columns - spring-data-jpa

#Column(length = 11)
private String mobileNo;
#Column(length = 20)
private String accountType;
The above is my entity class where i did not define any explicit column names under #column for my variables.
The corresponding column names for the above variables in my table are as mobile_no and account_type respectively - though my entity class variables and column names are bit different but it was working - as spring jpa was handling that naming conventions implicitly.
Now i have defined connections to multiple datasources by defing two configuration classes for two datasorces - but now the implicit #column names as mentioned above is not working.
I dont want to mention the explicit column names with #column in my entity class -
Need any suggestions to make it work with multiple datasorce configurations also - in the same way as it used to work with implicit column names with single database configuration.

Related

PostgreSQL function used in QueryDSL is not working, returns ERROR: syntax error at or near "."

This is my very first question on stackoverflow, so sorry in advance if anything is not as precise as it should be
In my project, I use Hibernate (as ORM framework) with QueryDSL lib, PostgreSQL as a database.
Basically, I need to check the size of a list 'arr', which is a property of some 'X' class, so I googled and found a way to use postgres functions with querydsl as follows (before you ask, I can't use native queries by the requirements):
BooleanBuilder builder = new BooleanBuilder();
builder.and(Expressions.booleanTemplate("function('array_length', {0})", qX.arr)
.castToNum(Integer.class).gt(0));
Everything compiles fine, but when the repository method is being called, I get an error:
ERROR: syntax error at or near "." Position: ...
I checked everything, but there are no "." in that position and near positions as well.
However, after setting spring.jpa.show-sql=true I found out that there is indeed a "." symbol somewhere in that position, and the result SQL statement looks like this:
... and cast(array_length(.) as int4)>?
which means, that JPA can't put my 'arr' inside the array_length() function (is that so?)
Why does this happen? Am I doing something wrong?
Thank you in advance
My entity class looks like that:
#EqualsAndHashCode(callSuper = true)
#Entity
#Table
#Data
#NoArgsConstructor
#TypeDefs({
#TypeDef(name = "list-array", typeClass = ListArrayType.class)
})
public class X extends BaseClass {
// private fields
#Type(type = "list-array")
#Column(name = "arr", columnDefinition = "bigint[]")
#ElementCollection
#OrderColumn
private List<Long> arr;
}
I tried without #ElementCollection and #OrderColumn annotations but that gives me cast errors
#ElementCollection and #OrderColumn are causing a first problem here. After they are removed (and the schema is setup correctly), the function call (SQL template) needs to be corrected.
The problem with #ElementCollection and #OrderColumn is that they represent an alternative approach for storing lists/arrays as part of an entity.
#ElementCollection stores the elements in a separate table, with each element in a separate row (each referencing the entity). To "remember" the correct order, an #OrderColumn is needed as part of the separate table, since rows are returned in arbitrary order if no order is specified (https://stackoverflow.com/a/20050403).
In contrast, ListArrayType and #Column(columnDefinition = "bigint[]") will enable saving the sequence of elements in one column of an entity row. Therefore, no separate table is used, and since the elements are not saved in separate rows, no additional order information is needed.
So without #ElementCollection and #OrderColumn the list mapping is already correctly setup. Be aware that your schema might currently be in a bad state, and you need to make sure that there is a bigint[] column in the entity table (can e.g. be auto-created by hibernate when #ElementCollection and #OrderColumn are removed).
2. Fixing the PostgresQL function call: array_length needs a second argument indicating the dimension of the array along which the length is returned (https://www.postgresql.org/docs/current/functions-array.html). So specifying the template string as follows should get you the correct result:
"function('array_length', {0}, 1)"
("1" being the requested array dimension).

Map two fields to one database column

Question: Am I somehow able to map two fields of my Entity class to only one Column in the Database?
Scenario: The database is not fully normalized. There exists one Column which contains a composite information. It is not my actual use case, but an comprehensible example might be X- and Y-coordinate of a point in the plane. So the Database may contain a String 12:45 and the Entity class should contain only two integer field x width value 12 and ywith value 45.
Currently the Entity class has just two additional getter and setter for x and y and performs the proper translation. But I am wondering if there is a way to let JPA do this for me magically in the background.
I am already working with custom converter classes, e.g. for a proper mapping between between enums and database columns, but this works only for a "one-to-one" mapping between the field in the Entity class and the column in the database.
Of course it would be the most preferable way to redesign the table in the database, but that's not an option at the moment.
Vendor specific solutions are also fine.
2 Entity fields into one database column can be done fairly simply by specifying JPA use your accessor in the entity to handle the conversion:
#Entity
#Access(AccessType.FIELD)
class myEntity {
#Id
int id;
#Transient
String x;
#Transient
String y;
#Mutable //EclipseLink specific to prevent change tracking issues
#Access(AccessType.PROPERTY)
#Column(name="yourDatabaseFieldName")
private String getCoords() {
return x+":"+y;
}
private void setCoords(String coords) {
//parse the string and set x+y.
}
EclipseLink and Hibernate have transformation mappings that are able to handle the reverse; 2 or more database fields into one java property but this is outside of JPA.

EclipseLink: default column names are changed to uppercase

I have the following entity:
#Entity
public class SomeEntity{
#Id
#Column(name = "id")
private Integer id;
private String foo;
//+getters and setters
}
So, ecpliselink will generate the following query:
SELECT t1.id, t1.FOO FROM ...
I've noticed that all default column names (which I didn't set via #Column) are changed to uppercase. I tried to set eclipselink.jpa.uppercase-column-names to false but it didn't help. How can I make eclipselink get the column names from the class fields without modification?
JPA standardizes the names to uppercase. With the property eclipselink.jpa.uppercase-column-names your're only able to force JDBC return column names in upper case in order to match with default naming in upper case.
If you don't want to use the Annotation #Column to overwrite the default naming of your columns, you could use a SessionCustomizer or a DescriptorCustomizer. Both ways will work with eclipselink and are very well described on this site Link with example of SessionCustomizer & :DescriptorCustomizer

Hibernate Envers rev column data type is Integer

I am using Hibernate Envers in my application to store audit trail data, all audit related information are storing in *_AUD table correctly. However, the data type of rev column in all _AUD table is Integer data type. I am expecting a big int data type because the maximum range of integer data type is 2147483647. Is there a way to change the data type to big int?
By default, the Envers implementation uses an Integer data type for the REV column.
In order to leverage a Long data type, you'll need to supply a custom revision entity with the appropriate annotations. Below is an example that will replace the existing default implementation while using a BIGINT compatible REV column.
#Entity
#RevisionEntity
public class CustomRevisionEntity implements Serializable {
#Id
#GeneratedValue
#RevisionNumber
private Long rev;
#RevisionTimestamp
private Long timestamp;
/* provide getter/setters */
}
NOTE: All audit tables will make their REV column's data type match that of the data type you use in the revision entity class.
There is an open JIRA HHH-6615 to migrate the default implementations to use Long instead of Integer based revisions; however, it does require that we consider upgrade paths as a implementation detail of that issue to account for existing users.
Until then, using a custom revision entity for new implementations is a workaround.

JPA Error compiling query when using Oracle objects within a query

The following JPA query doesn't compile -
SELECT a FROM CUSTOMER a WHERE a.activeCustomer = 'N' AND a.customerInfo.city IN :cityName ORDER BY a.customerId
where the table CUSTOMER in Oracle database has a base type - CUSTOMERINFO which in turn has various values such as -
city
country
This base type CUSTOMERINFO is extended by LOCALBUSINESSCUSTOMERINFO and MNCBUSINESSCUSTOMERINFO and a few others.
I think this may be due to the fact that when I define the column in my entity I define it as follows -
#Entity
#Table(name = "CUSTOMER", schema = "DBA")
#Converter(name="CustomerInfoConvertor", converterClass=CustomerInfoConvertor.class)
public class Customer implements Serializable {
#Basic
#Convert("CustomerInfoConvertor")
#Column(columnDefinition = "CUSTOMERINFO")
private ICustomerInfo customerInfo;
}
I have tried this query using SQL and it works fine but using it from JPA (JPQL) throws compilation error.
Thanks for your help!
You have mapped your customerInfo as a basic, so it is a basic in JPQL.
The column is of an Object object type?
In EclipseLink 2.3 you can map this as an Embeddable and the #Struct annotation, and use an Embedded mapping from the Customer. Does the customer table have other columns or is it a type table? If it is a type table, then use the #Struct to map it.