Hallo all.
I'm using EclipseLink as JPA provider in our project. As described here
we have e big problem with char trimming with a DB char column with EclipseLink
I tried the way to remove the jdbc bind parameter but I cannot make this change for production environment: I tried to write my own SessionCustomizer but it doesn't seem to work.
public class ContrattoSessionCustomizer implements SessionCustomizer {
/**
* #see org.eclipse.persistence.config.SessionCustomizer#customize(org.eclipse.persistence.sessions.Session)
*/
#Override
public void customize(Session session) throws Exception {
System.out.println("hello.....");
DatabaseLogin login = (DatabaseLogin)session.getDatasourceLogin();
login.setShouldTrimStrings(false);
}
}
I would like to migrate from EclipseLink to another JPA provider; yesterday I tried with hibernate but unfortunately to migrate to this provider I need to change my domain model, since it seems that hibernate does not support some mapping definition that I used with eclipse link.
Is there another good provider to test without make changes to my domain model mapping?
Kind regards
Massimo
Can't see how changing providers will help you, as it is a database issue.
You seemed to state that you solved the issue by disabling parameter binding?
Are you registering your SessionCustomizer in your persistence.xml?
Related
I have a project created from the ASP.NET Core Web Application template in VS. When run, the project creates a database to support the Identity package.
The Identity package is a Razor Class Library. I have scaffolded it and the models can be seen. The models are sub-classed from Microsoft.AspNetCore.Mvc.RazorPages.PageModel.
I am tracing the code to try and get a better understanding of how it all works. I am trying to find the path from the models to the physical database.
In the file appsettings.json, I see the connection string DefaultConnection pointing to the physical database.
In startup.cs, I see a reference to the connection string DefaultConnection:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
After this, I lost the trail. I can't find the link from a model in code to a table in the database. What is the code needed to perform a query like select * from AspNetUsers?
As #Daniel Schmid suggested , you should firstly learn the Dependency injection in ASP.NET Core.
ASP.NET Core has an excellent Dependency Injection feature through which this framework provides you with an object of any class that you want. So you don’t have to manually create the class object in your code.
EF Core supports using DbContext with a dependency injection container. Your DbContext type can be added to the service container by using the AddDbContext<TContext> method.
Then you can use the instance like :
public class MyController
{
private readonly ApplicationDbContext _context;
public MyController(ApplicationDbContext context)
{
_context = context;
}
...
}
or using ServiceProvider directly, less common :
using (var context = serviceProvider.GetService<ApplicationDbContext>())
{
// do stuff
}
var options = serviceProvider.GetService<DbContextOptions<ApplicationDbContext>>();
And get users by directly querying the database :
var users = _context.Users.ToList();
Please also read this article .
I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.
Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.
It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.
According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory
JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
The problem turned out to be that #Transactional annotations are not used automatically, and need the help of a TransactionInterceptor
Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.
However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?
Update:
While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.
The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:
We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.
That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.
To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.
I solved this by manually binding the EntityManager and EntityManagerFactory to the executing thread, before creating repositories with the JpaRepositoryFactory. This is accomplished using the TransactionSynchronizationManager.bindResource method:
emf = Persistence.createEntityManagerFactory("com.foo.model", properties);
em = emf.createEntityManager();
// Create your transaction manager and RespositoryFactory
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
// Make sure calls to the repository instance are intercepted for annotated transactions
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new MatchAlwaysTransactionAttributeSource()));
}
});
// Create your repository proxy instance
FooRepository repository = factory.getRepository(FooRepository.class);
// Bind the same EntityManger used to create the Repository to the thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
try{
repository.save(someInstance); // Done in a transaction using 1 EntityManger
} finally {
// Make sure to unbind when done with the repository instance
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
There must be be a better way though. It seems strange that the RepositoryFactory was designed to use EnitiyManager instead of an EntityManagerFactory. I would expect, that it would first look to see if an EntityManger is bound to the thread and then either create a new one and bind it, or use an existing one.
Basically, I would want to inject the repository proxies, and expect on every call they internally create a new EntityManager, so that calls are thread safe.
Looking at this answer, it says:
If you don't want to use an Application Client Container and instead just run the application client class through a java command, injection won't be possible and you'll have to perform a JNDI lookup.
However, given that I am trying to inject a DAO bean like the example shown here, if I cannot do the automatic injecting, it means my application must manually do the JNDI lookup and all the transaction begin/end that I would get for free if the #EJB actually worked.
However, since everything is all within the same Eclipse EJB Project (it also failed with the same null handle when I had my client code in a Dynamic Web Project), surely there must be an easy way to get it all working? Can anyone suggest what I am doing wrong?
Finally, this article suggests that DAOs are not needed, but if I replace within my EJB:
#EJB MyDao dao;
with the more direct:
#PersistenceContext private EntityManager em;
I still get the similar null value; is this the same injection failure problem?
NB: I have just noticed this answer:
This is a bug in Glassfish (apparently in the web services stack).
I am running v4.0 Build 89, which still has this bug? Does this mean I have to do all JPA actions the long-winded way?
I eventually found out that the problem/issue is that in order to use injection of the #PersistenceContext the class MUST be a bean itself. This is hinted at in the example on Wikipedia:
#Stateless
public class CustomerService {
#PersistenceContext
private EntityManager entityManager;
public void addCustomer(Customer customer) {
entityManager.persist(customer);
}
}
I could delete this question, but perhaps leaving this answer might provide a hint to someone, or at least show them a minimal working example of EJB and JPA.
I am trying to use Entity Framework data migrations, as described in this post.
However, when I try to execute the Enable-Migrations step, I receive the following error in Package Manager Console:
The target context 'MyDataContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory
So, I created a factory class that implements IDbContextFactory in the project that contains my DbContext class, but data migrations doesn't appear to recognize it.
Is there something that I should explicitly do to instruct data migrations to use this factory class?
I also hit this problem as i wrote my context to take a connection string name (and then used ninject to provide it).
The process you've gone through seems correct, here is a snippet of my class implementation if it's of any help:
public class MigrationsContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create()
{
return new MyDBContext("connectionStringName");
}
}
That should be all you need.
Like #Soren pointed out, instead of using IDbContextFactory, not supported on some earlier EF Core releases (i.e. EF Core 2.1), we can implement IDesignTimeDbContextFactory<TContext>, which supports the missing ConnectionString parameter.
For a settings.json based aproach, which you can use with either of the referred interfaces, check #Arayn's sample which allows us to define "ConnectionStrings:DefaultConnection" value path
Update 1
According to #PaulWaldman's comment, on EF Core 5 support for IDbContextFactory was reintroduced. For further details, check his comment below.
In my open jpa class, we have a method like this:
#Action(Action.ACTION_TYPE.CREATE)
public void createRecord(EntityObject fileStatus) {
EntityManager em = getEntityManager();
em.persist(fileStatus);
em.flush();
}
My question is with the #Action usage. I was of the impression that we use Annotations to avoid writing boilerplate code. In this particular method, what would be the boilerplate code that we would avoid by using the annotation? I think the method would look same even without the Annotation.
It's annotation used by IBM Rational Application Developer (RAD) - Related answer on IBM support page.
Annotations can be used for documenting purposes only - in that case they doesn't affect compiled code.
This one is most likely used by RAD to recognize specific JPA manager methods so it can list them in modeling tools there (this last is only mine guess).