Get the persistence context in the Web container

Source: Internet
Author: User
Tags xmlns java se

Get the persistence context in the Web container

Want to write this article, because read a few articles on the Internet, no one can really say how to correctly get the persistence context in the Web container, or do not know how to obtain, or there is an extremely large performance problem, or there is a thread security risk.

In the EJB container, if you are willing to inject a entitymanager into the container, you can leave everything to the container management. If you are willing to use scalable transactions, of course you already know how to manage Entitymanager. The specification is there, and there is nothing more to say. In the Java SE environment, there is no container to help you do anything, everything is created by you, and you are responsible for managing, shutting down, destroying. It's all your business, so it's easier to get the persistence method, not the action list.

I. Container management persistence context

In a Web container, a container-managed persistence transaction cannot use an extensibility transaction like an EJB container, and for a container to be managed it can only be a JTA transaction. And the data source must also be jta-data-source. People often find some persistence.xml on the internet, either using a local transaction or a non-JTA data source, and asking why I cannot successfully note entitymanager in a Web container.

There are two ways to let a container manage persisted transactions in a Web container, one for container injection and one for jndi lookups. Not everyone understands it, I see a book called <<EJB JPA Database persistence programming >> There are so many people on the internet (the more victims of such books!), the author makes it clear that "the container-managed Entitymanager can only be run in the EJB container, which means that the container-managed Entitymanager object is only available in the Ejb-jar package. Otherwise, you can only get the app-managed Entitymanager object.

In fact, some web containers do not inject entitymanager, nor can they be found through jndi. But the container does not support not the specification does not support if you use GlassFish, or resin 3.1.2 or more (currently 3.1.6) You will be able to easily get the entitymanager of container management.

<?xml version= "1.0" encoding= "UTF-8"?> <persistence

xmlns= "Http://java.sun.com/xml/ns/persistence" 

 xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" 

 xsi:schemalocation= "http://java.sun.com/xml/ns/ Persistence persistence_1_0.xsd " 

 version=" 1.0 ">

    <persistence-unit name=" Jpaunit "transaction-type=" JTA ">

     <jta-data-source>jdbc/__axman</jta-data-source>

        <class>com.axman.customereo </class>

    </persistence-unit>

</persistence>

As long as this persistence. xml file is in the Classpath, the Entitymanager can be injected correctly:

Remove extraneous content and comments for readability

public class Testaxman extends HttpServlet {

	

	@PersistenceContext (name= "Jpaunit")

	private entitymanager em;

	@Resource 

	private usertransaction utx; 



	protected void Service (HttpServletRequest request, httpservletresponse response) 

		throws Servletexception, IOException {

		PrintWriter out = Response.getwriter ();

		Customereo CE = new Customereo ();

		Ce.setname ("P4");

		Ce.setemail ("p4@email.com");

		Ce.setasset (12.7d);

		Ce.setcreatedate (New Java.sql.Date (New Java.util.Date (). GetTime ()));

		Utx.begin ();

		Em.persist (CE);

		Utx.commit ();

		Container management transactions do not need to be rolled back manually, as long as the container transaction is told to start and end boundary

	}



}

This injected Entitymanager is entirely managed by the container and does not do any Entitymanager related work. But is everything perfect?  Of course not, unlike the EJB container, a servlet that is equivalent to a stateful session bean is a multithreaded service, and the Entitymanager of an instance variable can potentially be accessed by multiple threads at the same time and there is a great security risk. Is this injection meaningful? Of course it makes sense that you can inject in a thread-safe module like Servletcontextlistener, and you can enjoy the convenience of container management as long as you can control the Entitymanager that doesn't allow multiple threads to access an instance variable at the same time. .

But everything has two sides, if you want to get convenience, you have to sacrifice the application scope of control and performance, to make multiple threads different when access to an instance variable Entitymanager, Ultimately, synchronization or mutual exclusion is required. That is, when one thread uses the variable Entitymanager, the other threads wait. If you can get Entitymanager managed by a container in the local method of threads (doxxx or the service method of the parent class),  That will greatly improve the performance of the program. "Container management" means, in fact, the container has produced some objects, you just need to use, do not need to be responsible for its production and destruction, the key is that the container produced such an object after you how to "get". By injecting only into instance fields, the thread method may get instant access through Jndi. Entitymanager "in the container. (In fact, as long as the container to change the implementation of the source code, you can also get the ServletContext object in the service method of dynamic instant injection, but this is not available to ordinary programmers).

The jndi-ref found through Jndi can also be configured via annotations or via web. Two methods: Inject Jndi-ref:

@PersistenceContext (name= "Persistence/jpaunit", Unitname= "Jpaunit") public

class Testaxman extends HttpServlet {

	protected void Service (HttpServletRequest request,httpservletresponse response) 

		throws Servletexception, IOException {

		Context env = (context) Newinitialcontext (). Lookup ("java:comp/env");

		Entitymanager em = (entitymanager) env.lookup ("Persistence/jpaunit"); 

		Query query = em.createquery ("Select C from Customereo C");

		List <CustomerEO> ls = query.getresultlist ();

	}

}

If you don't want to use annotations, you can configure them in Web. xml:

<persistence-context-ref>

	<persistence-context-ref-name>persistence/jpaunit</ persistence-context-ref-name>

	<persistence-unit-name>jpaUnit</persistence-unit-name>

 </persistence-context-ref>

You can then pass the same

Context env = (context) new InitialContext (). Lookup ("java:comp/env");

Entitymanager em = (entitymanager) env.lookup ("Persistence/jpaunit"); Find the Entitymanager.

It is necessary to note that the Jndi view itself is time-consuming, especially new InitialContext (). So you should create an env (equivalent to a workshop) in a global location. You can then use this env to find Entitymanager in the service method to improve performance in a number of ways, such as:

public class Testaxman extends HttpServlet {

	Context env = null;

	protected void init (ServletConfig config) throws servletexception {

		env = (Context) newinitialcontext (). Lookup (" Java:comp/env ");

	}

	protected void Service (HttpServletRequest request, httpservletresponse response) 

		throws Servletexception, IOException {

		Entitymanager em = (entitymanager) env.lookup ("Persistence/jpaunit"); 

		Query query = em.createquery ("Select C from Customereo C");

		List <CustomerEO> ls = query.getresultlist ();

	}

}
This is the best way to do this if you need container management persistence. Although Entitymanager every time to be in the service to lookup out, but it is
The local variable within the method does not have the multi-threaded security hidden danger as injected into the instance variable.

two. Application Management Persistence Context:

The application manages the persistence context, in fact the Entitymanager object is not generated and destroyed by the container. It is created by the application and is, of course, destroyed by the application. To create a persistence context by the application,   is to be createentitymanager by Entitymanagerfactory. The principle of who produces who is responsible, of course, the procedure to be responsible for the destruction. So the Entitymanager of application management must call the Close () method in the finally statement. So much for us to use it for inconvenience. But it is also because it is an application created, so it has a wide range of applications, JPA functionality is available in either the EJB container, the Web container, or the pure Java SE environment.

To get entitymanagerfactory in the Web container, you can also create it by injection and manually. Understand the meaning of "container management" should know that the injection is the object that the container has already produced, so entitymanagerfactory if it is container injected, The same does not require you to manually destroy, and if it is manually created, it will need to be manually destroyed. Simply stated that the Entitymanagerfactory object itself can also be managed by the container:

public class Testservlet extends HttpServlet {

	@PersistenceUnit (unitname = "Jpaunit")

	private Entitymanagerfactory emf;

	public void Service (...) throws xxxexceotion{

		entitymanager em = emf. Createentitymanager ();

		try{

			//invoke em;

		}

		finally{em.close ();}//Entitymanager itself is created by the application,

		//So it must be closed manually. If this is a write operation, the transaction must also be rolled back manually in the CACTH block
	}	

}

If you do not want to inject entitymanagerfactory through the container, simply call

Entitymanagerfactory emf = persistence.createentitymanagerfactory ("Jpaunit");

You can get a hand-created entitymanagerfactory, but remember to destroy it in the corresponding location where you created it. For example:

public class Testservlet extends HttpServlet {

	private entitymanagerfactory emf;

	void init (...) {

	  EMF = persistence.createentitymanagerfactory ("Jpaunit");

	}

	void Destory (...) {

	  if (EMF! = null) emf.close ();

	}



	public void Service (...) throws xxxexceotion{

		entitymanager em = emf. Createentitymanager ();

		try{

			//invoke em;

		}

		finally{em.close ();}//Entitymanager itself is an application created,

		//So must be manually closed.

	}

}

Because Entitymanagerfactory is a factory object, the above example is not good, the best position is injected into the serlvetcontextlistener and placed in the ServletContext, or manually generated in Contextlistener contextinitialized, destroyed in contextdestroyed, generated and placed in ServletContext for global access. That is, one application has only one factory, Entitymanager is generated on-the-fly in the service method through Entitymanagerfactory, which improves performance while ensuring thread safety. It can be said to be a very correct solution.

In the same book above, it is a good plan to get Entitymanager in the Dopost method after generating an instance object Entitymanagerfactory in the Servlet init method, but the author says it is unsafe, It is not a helper class to invoke threadlocal to get Entitymanager in the Dopost method. Is it possible that local variables within the Dopost method of different threads can also be accessed by other threads? Pure is the Huperzia serrata.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.