JPA - Mapping an Entity's field to a database function result - java

I'm using JPA 2.0. Is it possible to map an Entity's attribute (column) to the result of a function and then control the way it's persisted too?
Note: This is related to PostGIS. Since there is no native support for Geometry types in JPA/EclipseLink, I might do something like this:
#Entity
public class Foo {
#Column(name="geom", appendBeforeChange( ST_FromKml ))
public String kmlString;
}
In other words, I could store the geometry as a String in Java, but when EclipseLink writes it to the database, it should first call the database function ST_FromKml and provide the String, which will convert it to the Geometry type in the database...
I know it's a stretch, but figured I would ask...

I actually found a workaround with help from this post:
Are JPA (EclipseLink) custom types possible?
In Postgres, I create an implicit cast from String to Geometry:
CREATE OR REPLACE FUNCTION geom_in_text(varchar) RETURNS geometry AS $$
SELECT ST_GeomFromText($1::varchar);
$$ LANGUAGE SQL IMMUTABLE;
CREATE CAST (varchar AS geometry) WITH FUNCTION geom_in_text(varchar) AS IMPLICIT;
And now in Java, I just keep my Entity member variable as a String in WKT format. When Postgres see's the INSERT, it will recognize the avaiable implicit cast and not complain.
Note - I store WKT in my Entity class, but I could theoretically store KML and then update my function to call ST_GeomFromKml instead...

Related

Mapping derived columns to POJOs with RecordMapper in JOOQ

i have a table tickets where i insert ticket and have a field createdBy which stores the UserId Integer of the creator of that record. During fetching I join with users table and concat firstname and last name and my DTO has field createdBy of the concatenated name of creator. How can i map the derived field? this is my reference https://www.jooq.org/doc/3.13/manual/sql-execution/fetching/pojos/ and I cant seem to find such a scenario provided
the issue is not the join. the issue is mapping the string createdBy derived after the join whereas in the record class generated by jooq is an Integer because in the database table i store the userId.
List<MyTickets> mytickets = create.select(....FIELDS).from(TICKETS_).fetch().into(MyTickets.class);
#Override
public Field<Integer> field9() {
return Tickets.TICKETS_.CREATEDBY;
}
In my answer, I will assume that your computed column is going to be called CREATED_BY_NAME, not CREATED_BY, which is a name that's already taken, and to avoid confusion.
If this is something you do frequently, you have a few options that could be interesting to you:
Use views to generate this alternative CREATED_BY_NAME column. A lot of databases can insert into / update views as well, so you won't have a big penalty in using views to replace your tables. To your client logic, the origin of this column will be transparent. If you want to work with UpdatableRecord, you will have to tell jOOQ's code generator what the view's underlying primary key is using the synthetic primary key flag.
Similar to the above views, you could use computed columns on your tables, using the GENERATED ALWAYS AS ... syntax (or whatever your dialect uses for the syntax). Not all dialects support this, but it is a nice feature that turns tables into views without the extra view object.
If you want to keep computing this column manually in your jOOQ code, you could either write your own DTO / POJO objects, or extend the code generator with a custom code section, where you generate the relevant attribute / getter / setter. This approach only works for mutable POJOs, as you cannot modify the constructor of an immutable POJO.
You can also specify a base class for all of your affected POJOs and inject that base class using a generator strategy (programmatic or configurative). The base class could then implement all the getters / setters for columns like CREATED_BY_NAME.
You can also use structural typing instead. You don't have to map all the columns into your POJO. You could also map some columns into your generated POJO (excluding CREATED_BY_NAME) and map the CREATED_BY_NAME column separately. Just keep a reference to your jOOQ Result and/or Record, and perform several map / intoXYZ() calls on it.

How to translate Number(1,0) data type in oracle sql to hibernate?

I have a table that has a column as data type number(1,0) and title as answer. This column could hold either value of 1 or 0. I have a java entity model that represents this table using hibernate (v4.1.11). I am having a difficulty in mapping number(1,0) from oracle sql to hibernate. Do I even need an annotation for it? Having int type would be suffice?
#Entity
#Table(name="FOO")
public class Foo {
#Column(name="ANSWER")
#<what annotation?>
private int answer;
#Column is sufficient. Generally Type annotations are not needed unless you specifically want to override. Considering your case, it would be ideal to declare it as Boolean and use #Type NumericBooleanType or even YesNoType. If you want to override using custom type, please refer #TypeDef section in hibernate documentation https://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/.

underlying procedure for someMethod(SomeClass.class)

in hibernate to create criteria we use
Criteria criterea=session.createCritera(SomeClass.class)
It may be available in some other examples too but I am not able to understand the structure of these type of methods.
NOTE this is an example I am trying to put to understand use of SomeClass.class like arguments
my question here is what is purpose of SomeClass.class ? why do we need it, what is the advantages of using it as argument.
Edit its not a duplicate but have string connection to this question
What is this .class syntax?
If you attach .class to the end of a class name, you get the Class<T> object corresponding to the class.
Examples:
String.class returns an instance of Class<String>
Integer.class returns an instance of Class<Integer>
What can you do with a class object
Reflection! If you have access to a class object, you can do all kinds of cool stuff! You can call methods, get and set values of fields...
Why is this used in Hibernate?
I haven't used hibernate before, but this syntax is used in other libraries as well, especially in ORMs or JSON serializers. I'll use JSON serializers as an example as I'm more familiar with those.
In a JSON serializer, you need to give it a class object because it needs to get all the fields that you want to serialize to JSON. It uses reflection to get and set the values of those fields, then convert them to JSON. When it deserializes JSON, it finds the field that needs to be set with the name in the JSON. These operations require a Class object because without it, how can Java know which class should it find the field? Also, to create a new object with reflection, a Class is needed as well!
Hibernate provides many ways to handle the objects in relation with RDBMS tables.
One way is Session interface providing createCriteria() method which can be used to create a Criteria object.
As name says criteria, it is useful to execute queries by applying filtration rules and logical conditions of programmer wish.
For example:
Criteria obj=session.createCritera(Galaxy.class) // say SomeClass is Galaxy.class
List results = obj.list();
Here, criteria query is one which will simply return every object that corresponds to the Galaxy class.
We even can restrict the results with criteria, example add() method available for Criteria object to add restriction for a criteria query.
Following is the restriction to return the records with planet which has 7.4 billion population from Galaxy class:
Criteria cr = session.createCriteria(Galaxy.class);
cr.add(Restrictions.eq(“planet”, 75000000000));
List results = cr.list();

When Using sql2o, what is the org.sql2o.converters.ConverterException?

I am using the .executeScalar() method from the sql2o .jar file. I am getting this exception when using an Employee POJO, when I use .executeScalar(Employee.class) I am getting:
org.sql2o.converters.ConverterException: No converter registered for class: com.mack.sales.employees.Employee
I cannot find anything to help resolve this issue, any help is appreciated.
Converters are what sql2o uses to convert from database values to Java values. For instance, if one of your properties in your pojo is an integer, sql2o uses its integer converter to convert from any compatible database datatype (int, number, etc) to integer.
The executeScalar method will fetch only one value (first column and first row) from the database and convert it to a Java value. It is meant to be used with single value queries. For instance a select count(*) from table.
To fetch multiple columns and map their values to a pojo, you can use the executeAndFetchFirst() method.

Calling stored procedure in Oracle with complex object type parameters using EclipseLink

Due to the deprecation of JPublisher since Oracle 12c we're currently considering other ways how we can call stored procedures with complex object types as parameters instead of generated classes and JDBC.
It seems that EclipseLink JPA Extensions is the only tool that can help with it. Following the examples I found I'd be able to call procedures with simple types as arguments. But I wasn't able to annotate my entity classes so that they would map correctly to the PL/SQL Object types in the database when the objects are a bit more complex.
For example we have a stored procedure that has one input and one output parameter of the same Object type A. The type structure is following:
Object type A contains <- Table type B which is table of <- Object type C which contains <- Table type D which is table of <- Object type E.
I figured I shall use the #OracleObject for the Object types and #PLSQLTable for the Table types but I haven't found a way how to correctly combine them together.
I've tried the following:
// All annotations with the required elements
#Embeddable
#Struct
#OracleObject
public class A {
#Column(name = "B")
private B b;
// Getter and setter
}
#Embeddable
#Struct
#PLSQLTable (.., nestedType = "C")
public class B { }
#Embeddable
#Struct
#OracleObject
public class C {}
I've tried to add the #PLSQLTable with the proper annotation elements to class A and/or to class C but the Java and DB objects do not map to each other correctly and I'm getting the java.sql.SQLException: Invalid column typeduring the call.
I'd greatly appreciate if someone could explain to me how to use the annotations to tell the EclipseLink that Object A contains Table B of Object C.
Thank you very much.
Same issue here. I have been going down the path of Spring Data Oracle Extension project. However the example given is a simple pojo, not a complex object.
Despite a lack of examples anywhere I can find, I was able to pull a very complex object back via SqlReturnSqlData(), but can't seem to find a way to insert a complex object into an oracle stored procedure. I have yet to find any full example of how anyone is inserting custom complex Oracle Types. Via Spring or any other way.

Categories