Generic Data Access Objects [转]
The DAO interfaces An implementation with Hibernate Preparing DAOs with factories Preparing DAOs with manual dependency injection Preparing DAOs with lookup Writing DAOs as managed EJB 3.0 components A Better typed Generic DAO? You decide!
- The DAO interfaces
- An implementation with Hibernate
- Preparing DAOs with factories
- Preparing DAOs with manual dependency injection
- Preparing DAOs with lookup
- Writing DAOs as managed EJB 3.0 components
- A Better typed Generic DAO? You decide!
This is a pattern for Data Access Objects with JDK 5.0, from the CaveatEmptor example application. It is also explained in the book Java Persistence with Hibernate. Two links you might find useful: Sessions and transactions and Open Session in View.
This time I based the DAO example on interfaces. Tools like Hibernate already provide database portability, so persistence layer portability shouldn't be a driving motivation for interfaces. However, DAO interfaces make sense in more complex applications, when several persistence services are encapsulate in one persistence layer. I'd say that you should use Hibernate (or Java Persistence APIs) directly in most cases, the best reason to use an additional DAO layer is higher abstraction (e.g. methods like getMaximumBid()instead of session.createQuery(...) repeated a dozen times).
The DAO interfaces
I use one interface per persistent entity, with a super interface for common CRUD functionality:
<code><span><strong>public</strong></span> <span><strong>interface</strong></span> GenericDAO<t id><strong>extends</strong> Serializable> <span>{</span> T findById(ID id, <span><strong>boolean</strong></span> lock); List<t> findAll(); List<t> findByExample(T exampleInstance); T makePersistent(T entity); <span><strong>void</strong></span> makeTransient(T entity); <span>}</span> </t></t></t></code>
You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.
The DAO interface for a particular entity extends the generic interface and provides the type arguments:
<code><span><strong>public</strong></span> <span><strong>interface</strong></span> ItemDAO <span><strong>extends</strong></span> GenericDAO<item long> <span>{</span> <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> String QUERY_MAXBID = <span>"ItemDAO.QUERY_MAXBID"</span>; <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> String QUERY_MINBID = <span>"ItemDAO.QUERY_MINBID"</span>; Bid getMaxBid(Long itemId); Bid getMinBid(Long itemId); <span>}</span> </item></code>
We basically separate generic CRUD operations and actual business-related data access operations from each other. (Ignore the named query constants for now, they are convenient if you use annotations.) However, even if only CRUD operations are needed for a particular entity, you should still write an interface for it, even it it is going to be empty. It is important to use a concrete DAO in your controller code, otherwise you will face some refactoring once you have to introduce specific data access operations for this entity.
An implementation with Hibernate
An implementation of the interfaces could be done with any state-management capable persistence service. First, the generic CRUD implementation with Hibernate:
<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable> <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span> <span><strong>private</strong></span> Class<t> persistentClass; <span><strong>private</strong></span> Session session; <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span> this.persistentClass = (Class<t>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; <span>}</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>public</strong></span> <span><strong>void</strong></span> setSession(Session s) <span>{</span> this.session = s; <span>}</span> <span><strong>protected</strong></span> Session getSession() <span>{</span> <span><strong>if</strong></span> (session == <span><strong>null</strong></span>) <span><strong>throw</strong></span> <span><strong>new</strong></span> IllegalStateException(<span>"Session has not been set on DAO before usage"</span>); <span><strong>return</strong></span> session; <span>}</span> <span><strong>public</strong></span> Class<t> getPersistentClass() <span>{</span> <span><strong>return</strong></span> persistentClass; <span>}</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>public</strong></span> T findById(ID id, <span><strong>boolean</strong></span> lock) <span>{</span> T entity; <span><strong>if</strong></span> (lock) entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE); <span><strong>else</strong></span> entity = (T) getSession().load(getPersistentClass(), id); <span><strong>return</strong></span> entity; <span>}</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>public</strong></span> List<t> findAll() <span>{</span> <span><strong>return</strong></span> findByCriteria(); <span>}</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>public</strong></span> List<t> findByExample(T exampleInstance, String[] excludeProperty) <span>{</span> Criteria crit = getSession().createCriteria(getPersistentClass()); Example example = Example.create(exampleInstance); <span><strong>for</strong></span> (String exclude : excludeProperty) <span>{</span> example.excludeProperty(exclude); <span>}</span> crit.add(example); <span><strong>return</strong></span> crit.list(); <span>}</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>public</strong></span> T makePersistent(T entity) <span>{</span> getSession().saveOrUpdate(entity); <span><strong>return</strong></span> entity; <span>}</span> <span><strong>public</strong></span> <span><strong>void</strong></span> makeTransient(T entity) <span>{</span> getSession().delete(entity); <span>}</span> <span><strong>public</strong></span> <span><strong>void</strong></span> flush() <span>{</span> getSession().flush(); <span>}</span> <span><strong>public</strong></span> <span><strong>void</strong></span> clear() <span>{</span> getSession().clear(); <span>}</span> <span>/** * Use this inside subclasses as a convenience method. */</span> @SuppressWarnings(<span>"unchecked"</span>) <span><strong>protected</strong></span> List<t> findByCriteria(Criterion... criterion) <span>{</span> Criteria crit = getSession().createCriteria(getPersistentClass()); <span><strong>for</strong></span> (Criterion c : criterion) <span>{</span> crit.add(c); <span>}</span> <span><strong>return</strong></span> crit.list(); <span>}</span> <span>}</span> </t></t></t></t></t></t></t></t></code>
There are some interesting things in this implementation. First, it clearly needs a Session to work, provided with setter injection. You could also use constructor injection. How you set the Session and what scope this Session has is of no concern to the actual DAO implementation. A DAO should not control transactions or the Session scope.
We need to suppress a few compile-time warnings about unchecked casts, because Hibernate's interfaces are JDK 1.4 only. What follows are the implementations of the generic CRUD operations, quite straightforward. The last method is quite nice, using another JDK 5.0 feature, varargs. It helps us to build Criteria queries in concrete entity DAOs. This is an example of a concrete DAO that extends the generic DAO implementation for Hibernate:
<code><span><strong>public</strong></span> <span><strong>class</strong></span> ItemDAOHibernate extends GenericHibernateDAO<item long> implements ItemDAO <span>{</span> <span><strong>public</strong></span> Bid getMaxBid(Long itemId) <span>{</span> Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID); q.setParameter(<span>"itemid"</span>, itemId); <span><strong>return</strong></span> (Bid) q.uniqueResult(); <span>}</span> <span><strong>public</strong></span> Bid getMinBid(Long itemId) <span>{</span> Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID); q.setParameter(<span>"itemid"</span>, itemId); <span><strong>return</strong></span> (Bid) q.uniqueResult(); <span>}</span> <span>}</span> </item></code>
Another example which uses the findByCriteria() method of the superclass with variable arguments:
<code><span><strong>public</strong></span> <span><strong>class</strong></span> CategoryDAOHibernate extends GenericHibernateDAO<category long> implements CategoryDAO <span>{</span> <span><strong>public</strong></span> Collection<category> findAll(<span><strong>boolean</strong></span> onlyRootCategories) <span>{</span> <span><strong>if</strong></span> (onlyRootCategories) <span><strong>return</strong></span> findByCriteria( Expression.isNull(<span>"parent"</span>) ); <span><strong>else</strong></span> <span><strong>return</strong></span> findAll(); <span>}</span> <span>}</span> </category></category></code>
Preparing DAOs with factories
We could bring it all together in a DAO factory, which not only sets the Session when a DAO is constructed but also contains nested classes to implement CRUD-only DAOs with no business-related operations:
<code><span><strong>public</strong></span> <span><strong>class</strong></span> HibernateDAOFactory <span><strong>extends</strong></span> DAOFactory <span>{</span> <span><strong>public</strong></span> ItemDAO getItemDAO() <span>{</span> <span><strong>return</strong></span> (ItemDAO)instantiateDAO(ItemDAOHibernate.class); <span>}</span> <span><strong>public</strong></span> CategoryDAO getCategoryDAO() <span>{</span> <span><strong>return</strong></span> (CategoryDAO)instantiateDAO(CategoryDAOHibernate.class); <span>}</span> <span><strong>public</strong></span> CommentDAO getCommentDAO() <span>{</span> <span><strong>return</strong></span> (CommentDAO)instantiateDAO(CommentDAOHibernate.class); <span>}</span> <span><strong>public</strong></span> ShipmentDAO getShipmentDAO() <span>{</span> <span><strong>return</strong></span> (ShipmentDAO)instantiateDAO(ShipmentDAOHibernate.class); <span>}</span> <span><strong>private</strong></span> GenericHibernateDAO instantiateDAO(Class daoClass) <span>{</span> <span><strong>try</strong></span> <span>{</span> GenericHibernateDAO dao = (GenericHibernateDAO)daoClass.newInstance(); dao.setSession(getCurrentSession()); <span><strong>return</strong></span> dao; <span>}</span> <span><strong>catch</strong></span> (Exception ex) <span>{</span> <span><strong>throw</strong></span> <span><strong>new</strong></span> RuntimeException(<span>"Can not instantiate DAO: "</span> + daoClass, ex); <span>}</span> <span>}</span> <span>// You could override this if you don't want HibernateUtil for lookup</span> <span><strong>protected</strong></span> Session getCurrentSession() <span>{</span> <span><strong>return</strong></span> HibernateUtil.getSessionFactory().getCurrentSession(); <span>}</span> <span>// Inline concrete DAO implementations with no business-related data access methods.</span> <span>// If we use public static nested classes, we can centralize all of them in one source file.</span> <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>class</strong></span> CommentDAOHibernate <span><strong>extends</strong></span> GenericHibernateDAO<comment long> <span><strong>implements</strong></span> CommentDAO <span>{</span><span>}</span> <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>class</strong></span> ShipmentDAOHibernate <span><strong>extends</strong></span> GenericHibernateDAO<shipment long> <span><strong>implements</strong></span> ShipmentDAO <span>{</span><span>}</span> <span>}</span> </shipment></comment></code>
This concrete factory for Hibernate DAOs extends the abstract factory, which is the interface we'll use in application code:
<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> DAOFactory <span>{</span> <span>/** * Creates a standalone DAOFactory that returns unmanaged DAO * beans for use in any environment Hibernate has been configured * for. Uses HibernateUtil/SessionFactory and Hibernate context * propagation (CurrentSessionContext), thread-bound or transaction-bound, * and transaction scoped. */</span> <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> Class HIBERNATE = org.hibernate.ce.auction.dao.hibernate.HibernateDAOFactory.class; <span>/** * Factory method for instantiation of concrete factories. */</span> <span><strong>public</strong></span> <span><strong>static</strong></span> DAOFactory instance(Class factory) <span>{</span> <span><strong>try</strong></span> <span>{</span> <span><strong>return</strong></span> (DAOFactory)factory.newInstance(); <span>}</span> <span><strong>catch</strong></span> (Exception ex) <span>{</span> <span><strong>throw</strong></span> <span><strong>new</strong></span> RuntimeException(<span>"Couldn't create DAOFactory: "</span> + factory); <span>}</span> <span>}</span> <span>// Add your DAO interfaces here</span> <span><strong>public</strong></span> <span><strong>abstract</strong></span> ItemDAO getItemDAO(); <span><strong>public</strong></span> <span><strong>abstract</strong></span> CategoryDAO getCategoryDAO(); <span><strong>public</strong></span> <span><strong>abstract</strong></span> CommentDAO getCommentDAO(); <span><strong>public</strong></span> <span><strong>abstract</strong></span> ShipmentDAO getShipmentDAO(); <span>}</span> </code>
Note that this factory example is suitable for persistence layers which are primarily implemented with a single persistence service, such as Hibernate or EJB 3.0 persistence. If you have to mix persistence APIs, for example, Hibernate and plain JDBC, the pattern changes slightly. Keep in mind that you can also call session.connection() inside a Hibernate-specific DAO, or use one of the many bulk operation/SQL support options in Hibernate 3.1 to avoid plain JDBC.
Finally, this is how data access now looks like in controller/command handler code (pick whatever transaction demarcation strategy you like, the DAO code doesn't change):
<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span> <span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span> <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span> <span>// JTA: utx.begin();</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span> DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE); ItemDAO itemDAO = factory.getItemDAO(); UserDAO userDAO = factory.getUserDAO(); Bid currentMaxBid = itemDAO.getMaxBid(itemId); Bid currentMinBid = itemDAO.getMinBid(itemId); Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>); newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>), bidAmount, currentMaxBid, currentMinBid); <span>// JTA: utx.commit(); // Don't forget exception handling</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span> <span>}</span> </code>
The database transaction, either JTA or direct JDBC, is started and committed in an interceptor that runs for every execute(), following the Open Session in View pattern. You can use AOP for this or any kind of interceptor that can be wrapped around a method call, see Session handling with AOP.
Preparing DAOs with manual dependency injection
You don't need to write the factories. You can as well just do this:
<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span> <span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span> <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span> <span>// JTA: utx.begin();</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span> ItemDAOHibernate itemDAO = <span><strong>new</strong></span> ItemDAOHibernate(); itemDAO.setSession(HibernateUtil.getSessionFactory().getCurrentSession()); UserDAOHibernate userDAO = <span><strong>new</strong></span> UserDAOHibernate(); userDAO.setSession(HibernateUtil.getSessionFactory().getCurrentSession()); Bid currentMaxBid = itemDAO.getMaxBid(itemId); Bid currentMinBid = itemDAO.getMinBid(itemId); Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>); newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>), bidAmount, currentMaxBid, currentMinBid); <span>// JTA: utx.commit(); // Don't forget exception handling</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span> <span>}</span> </code>
The disadvantage here is that the implementation classes (i.e. ItemDAOHibernate and UserDAOHibernate) of the persistence layer are exposed to the client, the controller. Also, constructor injection of the current Session might be more appropriate.
Preparing DAOs with lookup
Alternatively, call HibernateUtil.getSessionFactory().getCurrentSession() as a fallback, if the client didn't provide a Session when the DAO was constructed:
<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable> <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span> <span><strong>private</strong></span> Class<t> persistentClass; <span><strong>private</strong></span> Session session; <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span> this.persistentClass = (Class<t>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; <span>}</span> <span><strong>public</strong></span> <span><strong>void</strong></span> setSession(Session session) <span>{</span> this.session = session; <span>}</span> <span><strong>protected</strong></span> <span><strong>void</strong></span> getSession() <span>{</span> <span><strong>if</strong></span> (session == <span><strong>null</strong></span>) session = HibernateUtil.getSessionFactory().getCurrentSession(); <span><strong>return</strong></span> session; <span>}</span> ... </t></t></t></t></code>
The controller now uses these stateless data access objects through direct instantiation:
<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span> <span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span> <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span> <span>// JTA: utx.begin();</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span> ItemDAO itemDAO = <span><strong>new</strong></span> ItemDAOHibernate(); UserDAO userDAO = <span><strong>new</strong></span> UserDAOHibernate(); Bid currentMaxBid = itemDAO.getMaxBid(itemId); Bid currentMinBid = itemDAO.getMinBid(itemId); Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>); newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>), bidAmount, currentMaxBid, currentMinBid); <span>// JTA: utx.commit(); // Don't forget exception handling</span> <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span> <span>}</span> </code>
The only disadvantage of this very simple strategy is that the implementation classes (i.e. ItemDAOHibernate and UserDAOHibernate) of the persistence layer are again exposed to the client, the controller. You can still supply a custom Session if needed (integration test, etc).
Each of these methods (factories, manual injection, lookup) for setting the current Session and creating a DAO instance has advantages and drawbacks, use whatever you feel most comfortable with.
Naturally, the cleanest way is managed components and EJB 3.0 session beans:
Writing DAOs as managed EJB 3.0 components
Turn your DAO superclass into a base class for stateless session beans (all your concrete DAOs are then stateless EJBs, they already have a business interface). This is basically a single annotation which you could even move into an XML deployment descriptor if you like. You can then use dependency injection and get the "current" persistence context provided by the container:
<code>@Stateless <span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable> <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span> <span><strong>private</strong></span> Class<t> persistentClass; @PersistenceContext <span><strong>private</strong></span> EntityManager em; <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span> setSession( (Session)em.getDelegate() ); <span>}</span> ... </t></t></t></code>
You can then cast the delegate of an EntityManager to a Hibernate Session.
This only works if you use Hibernate as a Java Persistence provider, because the delegate is the Session API. In JBoss AS you could even get a Session injected directly. If you use a different Java Persistence provider, rely on the EntityManager API instead of Session. Now wire your DAOs into the controller, which is also a managed component:
<code>@Stateless <span><strong>public</strong></span> <span><strong>class</strong></span> ManageAuctionController <span><strong>implements</strong></span> ManageAuction <span>{</span> @EJB ItemDAO itemDAO; @EJB UserDAO userDAO; @TransactionAttribute(TransactionAttributeType.REQUIRED) <span>// This is even the default</span> <span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span> Bid currentMaxBid = itemDAO.getMaxBid(itemId); Bid currentMinBid = itemDAO.getMinBid(itemId); Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>); newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>), bidAmount, currentMaxBid, currentMinBid); <span>}</span> <span>}</span> </code>
P.S. Credit has to be given to Eric Burke, who first posted the basics for this pattern on his blog. Unfortunately, not even the Google cache is available anymore.
A Better typed Generic DAO? You decide!
We are missing something on
<code><span>// Our common Model interface that an abstract Domain model will implement and all domain // models will extend.</span> <span><strong>public</strong></span> <span><strong>interface</strong></span> IModel<id><strong>extends</strong> Serializable> <span>{</span> <span><strong>public</strong></span> <span><strong>abstract</strong></span> ID getId(); <span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>void</strong></span> setId(<span><strong>final</strong></span> ID pId); <span>}</span> <span>// Our generic DAO, NOTE: MODEL's ID type is the same as ID now, which makes sense.</span> <span>// Also model type is more restrictive, dis-allowing all kinds of funky stuff to go in.</span> <span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<model><strong>extends</strong> IModel<id>, ID <span><strong>extends</strong></span> Serializable> <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span> <span><strong>private</strong></span> Class<model> persistentClass; <span><strong>private</strong></span> Session session; <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span> <span>// FIXME : I don't like magic number in the code, is there any way to fix 0 to something dynamic?</span> this.persistentClass = (Class<model>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; <span>}</span> <span><strong>public</strong></span> <span><strong>final</strong></span> <span><strong>void</strong></span> setSession(<span><strong>final</strong></span> Session pSession) <span>{</span> this.session = session; <span>}</span> <span><strong>protected</strong></span> <span><strong>void</strong></span> getSession() <span>{</span> <span><strong>if</strong></span> (session == <span><strong>null</strong></span>) session = HibernateUtil.getSessionFactory().getCurrentSession(); <span><strong>return</strong></span> session; <span>}</span> ... </model></model></t></id></model></id></code>
In addition, we could add things like:
<code><span><strong>public</strong></span> <span><strong>final</strong></span> String getRootAlias()<span>{</span> this.getPersistentClass().getSimpleName() + String.valueOf(<span>'_'</span>); <span>}</span> </code>
Alhough this is not necessary or part of the enhanced version, but when criteria API is in use, this comes in handy.

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SQL IF 語句用於有條件地執行 SQL 語句,語法為: IF (condition) THEN {語句} ELSE {語句} END IF;。條件可以是任何有效的 SQL 表達式,如果條件為真,執行 THEN 子句;如果條件為假,執行 ELSE 子句。 IF 語句可以嵌套,允許更複雜的條件檢查。

解決 Vue Axios 跨域問題的方法包括:服務器端配置 CORS 頭使用 Axios 代理使用 JSONP使用 WebSocket使用 CORS 插件

如何在 Apache 中配置 Zend?在 Apache Web 服務器中配置 Zend Framework 的步驟如下:安裝 Zend Framework 並解壓到 Web 服務器目錄中。創建 .htaccess 文件。創建 Zend 應用程序目錄並添加 index.php 文件。配置 Zend 應用程序(application.ini)。重新啟動 Apache Web 服務器。

多線程的好處在於能提升性能和資源利用率,尤其適用於處理大量數據或執行耗時操作。它允許同時執行多個任務,提高效率。然而,線程過多會導致性能下降,因此需要根據 CPU 核心數和任務特性謹慎選擇線程數。另外,多線程編程涉及死鎖和競態條件等挑戰,需要使用同步機制解決,需要具備紮實的並發編程知識,權衡利弊並謹慎使用。

無法以 root 身份登錄 MySQL 的原因主要在於權限問題、配置文件錯誤、密碼不符、socket 文件問題或防火牆攔截。解決方法包括:檢查配置文件中 bind-address 參數是否正確配置。查看 root 用戶權限是否被修改或刪除,並進行重置。驗證密碼是否準確無誤,包括大小寫和特殊字符。檢查 socket 文件權限設置和路徑。檢查防火牆是否阻止了 MySQL 服務器的連接。

本文介紹如何在Debian系統上有效監控Nginx服務器的SSL性能。我們將使用NginxExporter將Nginx狀態數據導出到Prometheus,再通過Grafana進行可視化展示。第一步:配置Nginx首先,我們需要在Nginx配置文件中啟用stub_status模塊來獲取Nginx的狀態信息。在你的Nginx配置文件(通常位於/etc/nginx/nginx.conf或其包含文件中)中添加以下代碼段:location/nginx_status{stub_status

PHPMyAdmin安全防禦策略的關鍵在於:1. 使用最新版PHPMyAdmin及定期更新PHP和MySQL;2. 嚴格控制訪問權限,使用.htaccess或Web服務器訪問控制;3. 啟用強密碼和雙因素認證;4. 定期備份數據庫;5. 仔細檢查配置文件,避免暴露敏感信息;6. 使用Web應用防火牆(WAF);7. 進行安全審計。 這些措施能夠有效降低PHPMyAdmin因配置不當、版本過舊或環境安全隱患導致的安全風險,保障數據庫安全。

vProcesserazrabotkiveb被固定,мнелостольностьстьс粹餾標д都LeavallySumballanceFriablanceFaumDoptoMatification,Čtookazalovnetakprosto,kakaožidal.posenesko
