Is it possible to use SQL syntax like FROM DUAL in JPA? - jpa

I am trying to create an independent project regardless of the type of DB using JPQL's #Query .
How do I implement the syntax below in JPA?
SELECT MY_SEQ.NEXTVAL FROM DUAL

Short answer:
For this kind of query, it's more productive to just use nativeQuery = true and use it normally.
To make it database agnostic as you want, you could theoretically just create a DUAL table in the new database.
Long answer:
The short answer is what you are actually looking for. But for the sake of other people who might fall here through Google for other related reasons though, if you really want it, you could theoretically transform Oracle's DUAL table into an entity by using #Subselect like so:
#Table
#Entity
#Subselect("SELECT dummy FROM DUAL")
public class DualEntity {
#Id
#Column(name = "dummy")
private String dummy;
}
Where dummy is the sole column in the DUAL table.
Although this doesn't seem very useful at first glance because most of this kind of queries are much easier to run as native queries, this does let us create repository interfaces for database functions when they aren't related to any actual tables in the database. Example:
#Repository
public interface DualRepository extends JpaRepository<DualEntity, String> {
#Query(nativeQuery = true, value = "SELECT MY_OWNER.MY_FUNCTION(:myParameter) FROM DUAL")
String myFunction(Long myParameter);
}
Which again, this function should probably be part of your code and not part of the database, but older applications tend to have this kind of stuff around. Procedures could also be called through #Query and could also benefit from this kind of mapping.

Related

Setting JPA behavior for importing entities from tables

How can I tell JPA how to behave with different column types in my database when it tries to generate the entities from tables?
For example when I have a column like the following in my MySQL:
`deleted` tinyint(1) NOT NULL DEFAULT 0,
I want in the generated entity by JPA have boolean instead of byte, but what the JPA will generate is something like this:
#Column(nullable=false)
private byte deleted;
However I want to have something like this:
#Column(nullable=false)
#Type(type = "org.hibernate.type.NumericBooleanType")
private boolean deleted;
I think there must be a way that I tell JPA how to translate the column types in my tables in the entities in Java!?
I don't like to modify the entities by hand!
If you're asking how to configure the Eclipse wizard to map TINYINT onto boolean, the answer is you probably cannot.
Using Hibernate tools looks more promising, though. There's a hibernate.reveng.xml config file you can use to control type mapping.
As a side note:
I don't like to modify the entities by hand!
Note that reverse engineering tools in general lack the business knowledge required to generate a business model structure that is completely sensible. You will likely have to do some tweaking (e.g you likely won't get any #ManyToMany associations, even if they are the more natural solution domain-wise).
In the last page of that wizard we can define the expected type for each column. The interesting part is, eclipse stores somehow the selected types for each column and in the future when you try to regenerate the entities you don't need to do this step times to times!

How can I use a wrapper object as a JPA entity without having a corresponding table in the database

I am building a system on top of an existing (old and messy) database. For this I'm building a JPA layer above the database, but I do not want to map my domain objects directly to the existing database tables.
I currently have a wrapper object that encapsulates 4 entities (data from 4 tables) in the database. Is there a way I can use this wrapper class as a parameter in a JPQL query?
It would be great if the wrapper class itself acted somewhat like a JPA entity, but without having the corresponding database table. Can this be achieved, and if so, how?
For example, how should I change Wrapper
public class Wrapper {
private FirstJpaEntity first;
private SecondJpaEntity second;
}
so that I can use something like
List<Wrapper> wrappers = ...;
TypedQuery<Wrapper> query = entityManager.createQuery(
"SELECT wrap" // This is probably where the problem lies: JPA needs a Type for `wrap`, but this type needs to be an #Entity which `wrap` is not
+ " WHERE wrap IN :wrappers"
+ " AND wrap.first.property = 1"
+ " AND wrap.second.property = 2"
, Wrapper.class);
query.setParameter("wrappers", wrappers);
I looked into making Wrapper an #Embeddable, hoping JPQL could figure out how to navigate through it, but alas #Embeddable objects cannot be queried directly.
Perhaps you can use Multiple Tables via Secondary Tables Annotation/Mapping in your wrapper class?
This way your wrapper can be composed of the four underlying tables but offer a cleaner interface to the application.

Attempting to use EF/Linq to Entities for dynamic querying and CRUD operations

(as advised re-posting this question here... originally posted in msdn forum)
I am striving to write a "generic" routine for some simple CRUD operations using EF/Linq to Entities. I'm working in ASP.NET (C# or VB).
I have looked at:
Getting a reference to a dynamically selected table with "GetObjectByKey" (But I don't want anything from cache. I want data from database. Seems like not what this function is intended for).
CRM Dynamic Entities (here you can pass a tablename string to query) looked like the approach I am looking for but I don't get the idea that this CRM effort is necessarily staying current (?) and/or has much assurance for the future??
I looked at various ways of drilling thru Namespaces/Objects to get to where I could pass a TableName parameter into the oft used query syntax var query = (from c in context.C_Contacts select c); (for example) where somehow I could swap out the "C_Contacts" TEntity depending on which table I want to work with. But not finding a way to do this ??
Slightly over-simplyfing, I just want to be able to pass a tablename parameter and in some cases some associated fieldnames and values (perhaps in a generic object?) to my routine and then let that routine dynamically plug into LINQ to Entity data context/model and do some standard "select all" operations for parameter table or do a delete to parameter table based on a generic record id. I'm trying to avoid calling the various different automatically generated L2E methods based on tablename etc...instead just trying to drill into the data context and ultimately the L2E query syntax for dynamically passed table/field names.
Has anyone found any successful/efficient approaches for doing this? Any ideas, links, examples?
The DbContext object has a generic Set() method. This will give you
from c in context.Set<Contact>() select c
Here's method when starting from a string:
public void Test()
{
dynamic entity = null;
Type type = Type.GetType("Contract");
entity = Activator.CreateInstance(type);
ProcessType(entity);
}
public void ProcessType<TEntity>(TEntity instance)
where TEntity : class
{
var result =
from item in this.Set<TEntity>()
select item;
//do stuff with the result
//passing back to the caller can get more complicated
//but passing it on will be fine ...
}

Logical Delete on EntityFramework

What is the elegant way of the soft delete on EntityFramework? I have already identified a property (database field) as deleted and always use this filter on linq statements.
Like
Foo Class
int NumberField
string Description
bool Deleted
contexts.Foos.Where(x=> !x.Deleted);
It is not feasible on complex queries.
I just looked these solutions..
Link 1, Link 2
Any help appreciated..
Yes this possible with EF via pattern.
If you use a Fascade/repository pattern and access EVERY time via that fascade.
eg
an implementation of an interface on ALL repository classes might look like this:
class MyRepositoryBase<T>....
public IQueryable<T> ValidQuerySet // this is not deleted check Set
{ get { return Context.Set<T>().Where(t => t.deleted != true);
}
}
You would access exactly as if it was the original DbSet.
EF will combine the conditions.
var myQuerySet = MyRespository<T>.ValidQuerySet.Where(t=>t.foo == "bar");
Instead of directly querying your context you might want to consider creating repositories over the context class itself (like found on this site). What you'll be able to do then is whenever you're querying for records (such as by using the Filter<T>(Expression<Func<T, bool>> predicate) method of the repository you can always do the following:
return Context.Set<Foo>().Where<Foo>(x => !x.Deleted).Where<Foo>(predicate).AsQueryable<Foo>();
What would be even better is if you were to implement that soft delete in more than one object type and then pull that into an abstract class (call it SoftDeleteable, for example), and so then your Filter method signature could be:
public virtual IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : SoftDeletable
You probably not going to like my answer, but the "less painful" way I can think of needs lots of Stored Procedures: 1 per each Entity, whereas all you do is if exists UPDATE foo Deleted = True. Mine usually look like this
PROCEDURE [dbo].[SP_Address_UnSet]
#ID bigint
AS
BEGIN
DECLARE #IsInactive bit
SELECT #IsInactive = IsInactive
FROM [Address]
WHERE AddressID = #ID
IF (0 = ##ROWCOUNT)
RETURN -1
-- implicit else
IF (1 = #IsInactive)
RETURN 0
-- implicit else
UPDATE [Address]
SET IsInactive = 1
WHERE AddressID = #ID
RETURN ##ROWCOUNT -- should be 1
END
Then on each entity map to that SP.
You COULD have 1 single SP, and pass the table name as a param, but since you can't use it directly in T-SQL via dynamic query, you would have to build sub executions (and worry avout SQL injection!!)
Exec('SELECT * FROM ' + #tableName)
Global Query Filters (EF Core) and Entity Framework Interceptors (EF 6+) are new features that added on EntityFramework in order to use on this kind of problems.
I find it's very painful to do "soft delete" this way:
you have to remember this flag everywhere when you do data access.
Yes, you can wrap it around some repository patter, but you still
have it everywhere.
Your table is quickly filled with "deleted"
entries, and make reporting, analysis not efficient.
I will suggest you just put hard "Deleted" entries into different table or databases, it will save you time in long run.

MyBatis mapping properties to database columns when inserting & updating (using annotations)

I'm just starting to learn MyBatis and I'm wondering, when I'm creating insert or update queries, is there a way that I can make property names a bit more friendly to refactoring? I'll explain in more detail:
I have constants in all of my domain classes that can be used to reference property names. In my opinion, it cuts down on typos and makes refactoring a bit easier.
public static final String FIRST_NAME = "firstName";
private String firstName = "";
When I create a MyBatis select statement using annotations, I can do something like this:
#Select("SELECT ID, FIRST_NAME, LAST_NAME FROM CUSTOMERS WHERE ID = #{id}")
#Results({
#Result(property = CustomerDetail.ID, column = "ID"),
#Result(property = CustomerDetail.FIRST_NAME, column = "FIRST_NAME"),
#Result(property = CustomerDetail.LAST_NAME, column = "LAST_NAME")
})
CustomerDetail selectById(final int id);
If I refactor my domain object (CustomerDetail) and change property names, it ends up being fairly simple.
However, when I create a MyBatis insert statement using annotations, I have to do something like this:
#Insert("INSERT INTO CUSTOMERS (ID, FIRST_NAME, LAST_NAME) VALUES (#{id}, #{firstName}, #{lastName})")
void insertCustomerDetail(final CustomerDetail customerDetail);
In this case, if I refactor my domain object (CustomerDetail) and change property names, it's much more error prone. Is there a way I can use my constants without resorting to a bunch of string concatenation? Is it something I should even concern myself with?
As a total newbie, I was expecting the #Insert and #Update annotations to mimic the structure of the #Select annotation. For example (please note, the below are NOT valid MyBatis annotations):
#Insert("INSERT INTO CUSTOMERS (ID, FIRST_NAME, LAST_NAME)")
#Params({
#Param(property = CustomerDetail.ID, column = "ID"),
#Param(property = CustomerDetail.FIRST_NAME, column = "FIRST_NAME"),
#Param(property = CustomerDetail.LAST_NAME, column = "LAST_NAME")
})
void insertCustomerDetail(final CustomerDetail customerDetail);
Have I missed any options that would have the same effect as my above sample? Alternatively, is it possible for me to unit test MyBatis mappings to ensure no one is using property names that don't exist in my domain objects? Testing may be a better solution since it would also apply to XML based mappings. Thoughts?
Is it something I should even concern
myself with?
I don't think so. I understand your concern, and I see how such a feature could be beneficial to you, especially early in development when POJO's tend to change so often.
I don't think your objects fields will be refactored enough to justify the investment needed to provide this functionality.
I suggest you read about the #Param tag in the mybatis user guide. It's not exactly what your looking for here, but it is a way to decouple object field names to mybatis sql map variables. In my mind, I would take your approach over passing in individual feilds with a #Param.
In regards to unit testing your sql maps, i'm fairly certain that if you use an ognl expression that doesn't have a corresponding get method in the object you'll get an exceptions. i.e if you use #{someField}, and the object your passing in doesn't have a getSomeField() method, then you get exception.