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.
Related
Using Spring Boot and Spring Data JPA, I have a table which represents an enum value, and a corresponding entity that I want that one of its field will be 'all the possible values the enum can have', i.e. a field possibleValues that will be a select all on the other table. Preferably I don't want to have a relationship like #ManyToMany since:
It will always be a select all, I don't want to save to the database all the options and update them each time the enum values table changes.
I am going to have several enums, so for each enum create another many-to-many is less than ideal.
I've tried to find something like #Formula that will let me select all the values from another table, but it doesn't seem to work:
#Transient
#Formula("select e.name from EnumTable e")
private List<String> possibleValues;
results in possibleValues always being null, and if I remove the #Transient I have to define the relationship between the two entities.
For Enum value in database, I recommend using string (for object, you can use JSON to convert first before store and covert back after retrieve )
I have generated a number of JOOQ classes from my database. I want to easily filter my tables by customer while maintaining the strong type of my tables.
This is what I want to be able to do:
// Generated class books
JBooks books = JBooks.BOOKS;
// get ownershipCheck (this could be more complicated, possibly joining multiple tables)
Condition ownershipCheck = books.customer().ID.eq(currentCustomer);
// desired output that I can do further operations on
JBooks filteredBooks = selectFrom(books).where(ownershipCheck).asTable();
// a bunch of random operations using the functionality from JBooks
db.select(filteredBooks.AUTHOR, filteredBooks.PUBLISH_DATE, ...etc)
Unfortunately, I can't do this. I get a Table<JBooksRecord> instead and I see no way to cast my new Table to JBooks
This is being worked on through:
#8012 "Override Table.where(Condition) methods in generated tables"
#1969 "Add support for views expressed in jOOQ"
In short, a table can accept a predicate and the result is a modified table of the same table type, exposing the same type safe column expressions. In generated SQL, this can either produce a derived table or be inlined into the calling SQL statement.
As of jOOQ 3.11, these features are not yet available.
How can I create a custom jOOQ Record from existing two others, i.e. merge properties from two existing Record Objects.
For example:
CustomerRecord(id, name, surname),
ProductRecord(id, customer_id, description)
SELECT * FROM Customer JOIN Product ON Customer.id = Product.customer_id;
After such a query I'll get RecordImpl object and I want to have custom one with access to field properties from both tables.
There are several options to achieve what you're looking for.
Use views
One of them would be to simply create a view:
-- Potentially disambiguate the ID (and other) columns
CREATE VIEW CustomerAndProducts AS
SELECT * FROM Customer JOIN Product ON Customer.id = Product.customer_id;
The code generator would then pick up that view and generate a CustomerAndProductsRecord for you
Use your own CustomRecord
You can create your own TableRecord subtype by extending org.jooq.impl.CustomRecord as is documented here:
https://www.jooq.org/doc/latest/manual/sql-building/queryparts/custom-queryparts
They work almost like ordinary TableRecord types and can have your own set of getters / setters
Use any class you like
You don't have to use records. jOOQ can fetch your results into any kind of class (which may happen to be records, see above) using the following code:
List<MyClass> list =
DSL.using(configuration)
.select()
.from(CUSTOMER)
.join(PRODUCT)
.on(CUSTOMER.ID.eq(PRODUCT.CUSTOMER_ID))
.fetchInto(MyClass.class);
In the above example, the DefaultRecordMapper is applied to map between jOOQ's records and your class. See its Javadoc for details.
I have a String property of an entity, which is often repeated by other entities - which would (in traditional databases) be mapped to its own table.
For example: I could having a clothing entity, with each item of clothing having its own object or row. Each item will have a brand, but this brand (String) could be repeated by many other clothing items. - it should essentially be a manyToOne mapping, though brand is not an entity on its own, its just a String.
How would I do this in hibernate? Or should I rather create an entity for each brand and use ManyToOne?
Any help will be appreciated!
I think that, just in terms of database normalization (most specifically 3NF), if you are expecting a column to have repeated values, you should export those values to their own table and have a foreign key column. That way, if one of those values changed you could change them all at once.
That would allow you to use ManyToOne in Hibernate as well.
However, if that isn't possible, I would recommend using an Enum.
I have many tables in my DB with exactly the same structure: same columns names and types.
The only difference between these tables is the their names (which I can only know in runtime).
I would like to create a mapping of a class to a table but giving the name of the table only during runtime (no static #Table annotation).
Is it possible?
Is there any other way to achieve my goal?
Directly - no. Because this is not a regular use-case. Normally you should not have dynamcally-generated tables. It is a valid use when you move some records to an archive table (or tables), but otherwise avoid it.
Anyway, you can make that work: make a native query, and map the result to your non-entity object. You will be able to select from any table and transform the result to an object. However, you can't insert or update that way.
Don't think associating or changing the table mapped to an entity dynamically is possible.
You can check #MappedSuperClass, which will allow you to define all fields in a class once and inherit them, so that there is no repetition and entities are empty class with mappings.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1168
If you know the table name dynamically you can always instantiate the mapped class accordingly.