Entity A is marked as #Cacheable(false) and A holds a relationship to another entity class B which is cacheable by default.
#Entity
#Cacheable(false)
public class A {
// ...
#xxxToOne B b;
}
What is going to happening, when I load an A instance through the EntityManager, when the related B instance is already available in the (2nd Level) cache? Will the framework perform the JOIN on the database and load the entire information of B as well, or will it return the B instance from the Cache?
Does the FetchType influence this behaviour?
Is this clearly defined in the JPA Spec. or may it depend on the JPA vendor?
Related
I have a JPA entity that links to others -- something like this:
#Entity
class LinkRec implements Serializable {
...
#OneToOne
private OtherEntity otherTable;
...
}
So my logic eventually can delete this entity (calling the EntityManger.remove method), then I want to write to a log file what was done, including reference members of the otherTable object. Is this a permitted operation in JPA?
Is this a permitted operation in JPA?
Yes.
What JPA (underlying JPA provider) does when you invoke remove is just "mark" that the instance is expected to be deleted/removed. But even if the transaction is committed (and the instance deleted from the database) or not, the instance object remains the same. Any changes on its attributes depend on what you do.
Due to you mark the entity as removed you won't can refresh the instance's state from the database (call EntityManager.refersh method). You will get an IllegalArgumentException.
Be aware that, in other cases, you could screw up if you refresh the entity before loggin what you want.
I quote a text from the JPA specification (see Synchronization to the Database section) that could help you to understand the "JPA" behaivor
Synchronization to the database does not involve a refresh of any managed entities unless the refresh operation is explicitly invoked on those entities or cascaded to them as a result of the specification of the cascade=REFRESH or cascade=ALL annotation element value
The relevant line in the spec is:
After an entity has been removed, its state (except for generated state) will be that of the entity at the point at which the remove operation was called.
Since this is all I can find on the subject in the spec, I would say that it could vary from implementation to implementation. In my opinion, this makes what you are tying to do dangerous. It may work in one JPA implementation and not another, or work in one version and not in an upgrade.
If I had to guess on implementations, I would say that #OneToOne objects will probably work okay. Where I would worry is with things like #OneToMany. In the case of Hibernate for example: this collection may be hydrated and in memory, but it may also point to a proxy. If it is a proxy and you call the getter it will check with the database for the collection and fail to load it because the object is gone.
I am studying JPA in Spring application and I have some doubts related to the #Entity annotation.
So I have a model class like this:
#Entity
#Table(name= “T_CUSTOMER”)
public class Customer {
#Id
#Column(name=“cust_id”)
private Long id;
#Column(name=“first_name”)
private String firstName;
#Transient
private User currentUser;
...........................
...........................
...........................
}
Ok, I know that the #Entity annotation is on the class level and it means that the fields of the object that are instances of this class are to be mapped to the field of the T_CUSTOMER database table.
But why in JPA it is mandatory to use #Entity annotation and I cannot only use the #Table annotation to map a model object to a specific database table? It have some other meaning\behavior that actually I am missing?
What am I missing? What is the exact meaning of the #Entity annotation?
#Entity annotation defines that a class can be mapped to a table. And that is it, it is just a marker, like for example Serializable interface.
And why #Entity annotation is mandatory? ... well, it is the way how JPA is designed. When you create a new entity you have to do at least two things
annotated it with #Entity
create an id field and annotate it with #Id
Anything else is optional, for example table name is derived from entity class name (and therefore #Table annotation can be optional), table's columns are derived from entities variables (and therefore #Column annotation can be optional), and so on ...
JPA is trying to provide a fast and easy start to developers who want to learn/use this API, and giving developers option to configure as few things as possible to make something functional is one of the ways how this API wants to achieve this "easy to use/learn" goal. Hence the #Entity annotation (together with #Id annotation) is the minimum you have to do in order to create an entity.
Entities in JPA are nothing but POJOs representing data that can be persisted to the database. An entity represents a table stored in a database. Every instance of an entity represents a row in the table.
More about the entities:
https://www.baeldung.com/jpa-entities
Entities represent persistent data stored in a relational database automatically using container-managed persistence.They are persistent because their data is stored persistently in some form of data storage system, such as a database: they do survive a server failure, failover, or a network failure. When an entity is reinstantiated, the state of the previous instance is automatically restored.
An entity models a business entity or multiple actions within a single business process. Entities are often used to facilitate business services that involve data and computations on that data. For example, you might implement an entity to retrieve and perform computation on items within a purchase order. Your entity can manage multiple, dependent, persistent objects in performing its tasks.
Entities can represent fine-grained persistent objects, because they are not remotely accessible components.
An entity can aggregate objects together and effectively persist data and related objects using the transactional, security, and concurrency services of a JPA persistence provider.
I've been scouring the net, but haven't found anything useful. I have a POCO class that I want to wire up to a stored procedure in Entity Framework 6.x. I've see how to do it in the Fluent API for Inserts, Updates, and Deletes.... but not for just straight Reading.
I found this: EF 6 Code First Stored Procedure - Read Only, but it looks like it's just a method on some controller somewhere.
Is there a way where I can call the context like I would any other Entity. I.E.,
ctx.Products.Where( p => p.ProductId == productId )?
I would approach this is one of two ways.
Domain / POCO mapping
If the underlying issue is a mismatch between your Entity Framework model POCO's and your (presumably purely logical) domain, I would match the EF model directly to the database schema and them map them across to domain types accordingly. I.e have a separate domain model to your EF poco's. The mapping work previously done by your proc would then be done within the domain mapper.
Abstract DbContext usage behind Repositories
Rather than having consumers directly query the context, you could abstract the context behind entity repositories and map between a SqlQuery calling a proc and your POCO's in the repository methods
E.g. here is some rough code:
public class MyEntityRepository()
{
public ICollection<MyEntity> GetAll()
{
return _myContext.SqlQuery<MyEntity>("exec myProc", params);
}
}
Neither of these options would be quick to implement and introduce into your codebase though.
I am trying to build a generic repository that allows querying against domain classes.
My Repository interface looks like the following:
public interface IRepository<T>
{
T Get(int id);
IQueryable<T> Query();
void Add(T model);
void Remove(T model);
}
Given I have an UserEntity entity framework class and a User domain class, I want to query against the User. The UserEntity should not be exposed to other services, because it should be internal to the Entity Framework layer.
A query like userRepository.Query().Single(user => user.UserName == "Toni") should return a User domain class. However internally it should query against an IDbSet<UserEntity> returned from my entity framework. The Expression Tree (which contains the Single query operation) should be attached to a query against IDbSet<UserEntity>. After querying against IDbSet<UserEntity> I want to convert the UserEntity to a User domain class. Is this possible?
I have in mind to cerate an IQueryable implementation for my User class that internally queries against UserEntity.
public class MappedEntityQuery<TModel, TEntity> : IQueryable<TModel>
{
}
Code First requires the convention to have all IDbSet properties to access the tables to be in the DbContext
That is not true. You don't need to have any set declared in the context if you provide mapping to the entities in the model builder. In your case you should declare mapping through EntityTypeConfiguration<T> and ComplexTypeConfiguration<T> derived classes. You can create any DbSet instance of mapped entity type by calling Set<T>() on the context.
However for this project I am using a Database First approach, which also does not allow to load compose a DbContext using entities from different projects, because you have to specify the Database metadata in one single metadata file (which will be embedded).
That is true only partially. EDMX metadata must be in the single file embedded in the main project but entity classes do not have to if you use your own instead of auto-generated. So your proposed approach should work.
But if you really want to achieve modularity you should not use EDMX. If you decide to add or change any module in the future it would require changing central project as well but that can affect all other modules - it breaks the idea of modularity, doesn't it?
If i havea JPA class Person and Person has reference to a JPA class Address. If I call Person.persist(), will Address.persist() be called implicitly?What if the hierarchy was longer. Would all the child classes be persisted implicitly?
From the JPA specification:
The semantics of the persist operation, applied to an entity X are as
follows: ...
the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities is annotated with the
cascade=PERSIST or cascade=ALL annotation element value or specified
with the equivalent XML descriptor element.