I have a table with 11 columns, but I need to get only 2 of them in my application, I'm using spring/hibernate/DAO combination. For now I have a domain class which includes all 11 fields, and mapping file which maps all 11 columns in table. How do I use get just 2 of them not all?
Either:
Use projections - Pro: nothing to add - Con: Not typesafe (the result is a List of rows where each row is anObject[]):
select f.foo, f.bar from FatEntity f
Use a constructor expression in the SELECT clause (the specified class is not required to be an entity or to be mapped to the database) - Pro: typesafe solution - Con: More classes, unless you reuse FatEntity as holder in which case many fields will be null:
select new com.acme.FatEntityDetails(f.id, f.foo, f.bar) from FatEntity f
Note that if an entity class name is specified in the SELECT NEW clause, the resulting entity instances are in the new state (no persistent identity).
Use another entity mapped on the same table with only the required fields - Pro: It's a real entity that you can modify and update - Con: More classes.
from LightEntity
The main differences between #2 and #3 are:
2 doesn't require the holder to be an entity at all.
the holder in #2 could be an entity mapped on another table.
if #2 returns entities, they are in a new state (this might be a problem, or not).
Try:
SELECT myEntity.one, myEntity.two FROM MyEntity myEntity
You can even do :
SELECT new MyEntityDescription(myEntity.one, myEntity.two) FROM MyEntity myEntity
to get a list of entity descriptions.
If you never need more than those 2 columns of the table, you could change your hibernate mapping to map only those 2 needed columns to the entity class. Only map those table columns you want to access in your application. Keep in mind, that database constraints on the "ignored" columns can be violated like not null constraints, foreign keys or unique constraints.
Related
I'm doing a left join of Table A and Table B and trying to fetch the results into a custom POJO which has fields from both Table A and Table B as follows:
List<MyCustomPojo> res = create.select()
.from(TABLE_A)
.leftJoin(TABLE_B)
.on(TABLE_A.MY_CODE.eq(TABLE_B.MY_CODE))
.fetchInto(MyCustomPojo.class);
It works fine for all the fields except for the field myCode the one on which these two tables are joined. For me the values for myCode were picked up from the right table, Table B, which is NULL for all of those records in Table A that do not have a corresponding entry in Table B. I would like to know how jooQ decides which field to map to POJO and if this behavior is documented anywhere.
My goal is to fetch all the fields from Table A and Table B into the custom POJO such that myCode is picked up from the left table. I would appreciate your advice on the right way to achieve it.
The default behaviour of ResultQuery.fetchInto(Class) (and most other into(Class) methods) is specified in DefaultRecordMapper. It can be overridden globally by providing a custom RecordMapperProvider in your Configuration.
In your particular case, DefaultRecordMapper will map all values from your records in field order. If there's a column that appears twice, it will be mapped twice, meaning that the second value will persist in your resulting object. There are two easy workarounds:
Don't select the "wrong" myCode. This is really the most robust solution
List<MyCustomPojo> res = create
.select(TABLE_A.fields())
.select(/* all fields in TABLE_B except the ones you don't want */)
.from(TABLE_A)
.leftJoin(TABLE_B)
.on(TABLE_A.MY_CODE.eq(TABLE_B.MY_CODE))
.fetchInto(MyCustomPojo.class);
Use RIGHT JOIN instead:
Perhaps a bit of a hack, but this will quickly reverse the table order in your SELECT statement.
List<MyCustomPojo> res = create
.select()
.from(TABLE_B)
.rightJoin(TABLE_A)
.on(TABLE_A.MY_CODE.eq(TABLE_B.MY_CODE))
.fetchInto(MyCustomPojo.class);
Finally a use-case for RIGHT JOIN :)
Note, this is the only solution that will also prevent wrong values for other columns that "accidentally" share the same name.
Add the "correct" myCode field once more.
Another hack, but it will work around the issue you're experiencing:
List<MyCustomPojo> res = create
.select(TABLE_A.fields())
.select(TABLE_B.fields())
.select(TABLE_A.MY_CODE)
.from(TABLE_A)
.leftJoin(TABLE_B)
.on(TABLE_A.MY_CODE.eq(TABLE_B.MY_CODE))
.fetchInto(MyCustomPojo.class);
I have an entity called Person which represent person_tb
person_tb has 10 fields that includes zip and country. But these columns are not specified in the Person entity. The entity contains only 8 columns out of 10 columns in the actual table.
Can I still run the query against person entity referring to the non-existing fields (but existing in the actual table)? (I am assuming its not possible)
If the above is not possible, can I write native query based on the missing fields in the entity?
Yes - you can use Native SQL Queries for this purpose.
I have two entities with a many-to-one relationship between them. Many B entities are related to an A entity. My B table has an A_ID column. In some situations, we may have a B entity that has an A_ID but doesn't relate to any row in A. I know this isn't ideal but it's part of the old system and we can't really touch this portion of the code.
With proper Hibernate entities, I'm able to add B entities when we have an A entity to associate with using B's setA() method and B's getAs().add() method. I don't see any way to deal with the case where I'd like to add a B entity that isn't associated with an A entity (B's A_ID = 10, for example, where there's no A with an ID = 10). Is this possible or am I stuck breaking our entity hierarchy at this point and dealing with it manually?
Is there some way to add a setAId() to the B entity and either use that or the setA() method but not both? Will Hibernate allow this? When I try to add the getter and setter on B, I get the following error:
MyHibernateException: Hibernate SessionFactory creation failed, hibernateCfgFileNm=hibernate.xml
...
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: test.B column: A_ID (should be mapped with insert="false" update="false")
Sorry for not providing code. I think this explanation is sufficient but if code is required, I can add it.
With my understanding of entity relations (I assume you're mapping these with standard JPA #ManyToOne / #OneToMany relations?) I believe you're going to run into some fun issues here.
I would create my A entities using a sequence generated ID, and allow for 'placeholder' A entities which do nothing but carry the A_ID from the old system. Just make your code aware that not every A entity will be a full entity (it may just place-hold those A_IDs you mentioned above) and gracefully handle it, allowing you to always provide an A entity, with an ID decoupled from the legacy system.
I don't think you'll be able to map the relation to the same column and set a value in the column without the relation causing issues -- unless perhaps if you mark the relation as LAZY fetch and catch the exceptions which are bound to occur when it tries to resolve the non-existent Entity A. That may also work -- in that case, try to map the relationship column as read-only (insert="false" update="false"), and do everything with the setAId(id). You may need to have your setA(A) method only operate on IDs rather than managed collections, since reading a collection will by it's very nature fetch any related rows.
Your best bet is to decouple from the IDs of the legacy system if the semantics of the legacy IDs loosely translate to 'here, this ID may be a null object.'
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.
I have a data model in which a number of entities inherit some common attributes from a single superclass entity. I am using InheritanceType.JOINED on the superclass, which causes Hibernate to create a single table for attributes defined in the superclass, with subclass tables containing only columns that are added by the subclass (so to load the attributes for a subclass instance, a join is performed between the two tables). That is all working fine.
What I'd like to do, however, is specify a unique constraint that includes fields in both the subclass and superclass tables. For instance, say that my superclass entity is something like:
Thing: {id, name}
...and then I have some subclass entities like:
Company: {address} //inherits 'id' and 'name' from 'Thing'
Employee: {company} //inherits 'id' and 'name' from 'Thing'
...and I want to configure Hibernate to automatically enforce that a given Company cannot have two Employee's with the same name. The company field is in the Employee table, but the name field is in the Thing table, so is there any way to get Hibernate to enforce this constraint, or do I need to do it programmatically whenever I add a new Employee?
If it's not possible in the Database it won't be possible with Hibernate. You can't create one constraint on multiple tables with SQL so neither in Hibernate.
You could work around this by creating a new Entity holding only the company and employee id and setting a unique constraint on those 2 fields but I would recommend enforcing this programmatically.
You could not use InheritanceType.JOINED, then everything ends up in a huge table, and you could write your constraint. As said before: What you want is just not possible in a relational DB.