ปัญหา
เนื่องจากในตอนแรกนั้น ผมพัฒนาระบบโดยใช้ eclipseLink แต่ทีนี้เกิดมีประเด็นว่า user อยากได้ full text search ซึ่งเท่าที่คิด solution ออก ก็มีเขียน lucene เพียวๆ กับใช้ hibernate ที่มี full text search ให้ ถ้าจะให้เขียน lucene ก็คงเหนื่อยน่าดู ก็เลยเลือก hibernate เพราะว่าน่าจะง่ายกว่า ผมก็เลยลองเปลี่ยนไปใช้ hibernate แต่ปรากฏว่า เกิดปัญหาเรื่อง lazy load in view ของ hibernate แต่ eclipseLink ไม่พบปัญหานี้ ผมก็เลยหาทางแก้ ด้วยการ config hibernate ให้ open session in view ตามที่คนอื่นๆ บอก แต่ก็ยังแก้ไม่ได้ ผมก็เลยคิดหาทางออกโดยการกลับไปใช้ eclipseLink เหมือนเดิม ส่วนตัวที่ต้องการทำ full text search ก็ค่อยใช้ hibernate จะได้ไม่ต้องมานั่ง test ระบบใหม่ทั้งหมด ก็เลยทำให้เกิดกรณีการ ใช้งานร่วมกันระหว่าง eclipseLink และ hibernate เกิดขึ้น โดยก่อนหน้านี้ eclipseLink ใช้ร่วมกับ spring data อยู่แล้ว แต่มันมีข้อกำหนดของ spring data ว่าใช้ได้แค่ 1 EntityManager เท่านั้น ผมก็เลยให้ eclipseLink ใช้ spring data ต่อไป ส่วน hibernate ซึ่งเอาไว้ทำเฉพาะ full text search ก็ไม่ได้ใช้ spring data ก็เลยสามารถแก้ปัญหานี้ได้ครับ จึงทำให้เกิด บทความนี้ขึ้นมา คือ "การ config eclipseLink ร่วมกับ hibernate โดย eclipseLink ใช้ spring data แต่ hibernate ไม่ได้ใช้"
ผมเลยเอาประสบการณ์นี้มาแชร์ให้กับทุกๆคนครับ
Resource Local Config
applicationContext-datasource.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <context:component-scan base-package="com.blogspot.na5cent" /> <context:annotation-config /> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- spring data use EclipseLink EntityManager (eclipseLinkEmf) spring data can use one EntityManager Only (EcelipsLink or Hibernate only not more than one) --> <jpa:repositories base-package="com.blogspot.na5cent.repositories" entity-manager-factory-ref="eclipseLinkEmf" transaction-manager-ref="transactionManager"/> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="eclipseLinkEmf"/> </bean> <!-- (JPA Transaction) .jpa.JpaTransactionManager --> <bean id="transactionManagerHibernate" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="hibernateEmf"/> </bean> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@YOUR_HOST:SERVICE_ID"/> <property name="username" value="USERNAME"/> <property name="password" value="PASSWORD"/> </bean> </beans>applicationContext-eclipseLink.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <bean id="eclipseLinkEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="ECLIPSELINK_PU"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistenceUnit.xml"/> <property name="dataSource" ref="dataSource" /> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect "/> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter "/> </property> </bean> </beans>applicationContext-hibernate.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"> <bean id="hibernateEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="HIBERNATE_PU"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistenceUnit.xml" /> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="database" value="ORACLE" /> </bean> </property> </bean> </beans>classpath:META-INF/persistenceUnit.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" 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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <!-- eclipseLink --> <persistence-unit name="ECLIPSELINK_PU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <non-jta-data-source>jdbc/hippo</non-jta-data-source> <class>com.blogspot.na5cent.model.Authorization</class> <class>com.blogspot.na5cent.model.BinaryDescriptor</class> <class>com.blogspot.na5cent.model.Document</class> <class>com.blogspot.na5cent.model.Folder</class> <class>com.blogspot.na5cent.model.Group</class> <class>com.blogspot.na5cent.model.Tag</class> <class>com.blogspot.na5cent.model.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <shared-cache-mode>NONE</shared-cache-mode> <validation-mode>NONE</validation-mode> <properties> <property name="eclipselink.logging.level" value="FINEST"/> <property name="eclipselink.logging.timestamp" value="false"/> <property name="eclipselink.logging.session" value="false"/> <property name="eclipselink.logging.thread" value="false"/> <property name="eclipselink.logging.parameters" value="true"/> <property name="eclipselink.cache.shared.default" value="false"/> <property name="eclipselink.target-server" value="SunAS9"/> <property name="eclipselink.weaving" value="static"/> </properties> </persistence-unit> <!-- hibernate --> <persistence-unit name="HIBERNATE_PU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>jdbc/hippo</non-jta-data-source> <class>com.blogspot.na5cent.model.BinaryFullTextEntry</class> <class>com.blogspot.na5cent.model.DocumentFullTextEntry</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/> <property name="hibernate.search.default.directory_provider" value="filesystem"/> <property name="hibernate.search.default.indexBase" value="${hibernate.search.default.indexBase}"/> <property name="hibernate.search.default.exclusive_index_use" value="false"/> <property name="hibernate.search.default.locking_strategy" value="native"/> </properties> </persistence-unit> </persistence>JTA(Java Transaction API) Config
applicationContext-datasource.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <context:component-scan base-package="com.blogspot.na5cent" /> <context:annotation-config /> <tx:annotation-driven /> <!-- (JTA Transaction) .jta.JtaTransactionManager --> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> <jpa:repositories base-package="com.blogspot.na5cent.repositories" entity-manager-factory-ref="eclipseLinkEmf"/> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <jee:jndi-lookup id="dataSource" jndi-name="JNDI_NAME" /> </beans>applicationContext-eclipseLink.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <bean id="eclipseLinkEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="ECLIPSELINK_PU"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect " /> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter "/> </property> </bean> </beans>applicationContext-hibernate.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"> <bean id="hibernateEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="HIBERNATE_PU"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="database" value="ORACLE" /> </bean> </property> </bean> </beans>classpath:META-INF/persistenceUnit.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" 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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <!-- eclipseLink --> <persistence-unit name="ECELIPSELINK_PU" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/hippo</jta-data-source> <class>com.blogspot.na5cent.model.Authorization</class> <class>com.blogspot.na5cent.model.BinaryDescriptor</class> <class>com.blogspot.na5cent.model.Document</class> <class>com.blogspot.na5cent.model.Folder</class> <class>com.blogspot.na5cent.model.Group</class> <class>com.blogspot.na5cent.model.Tag</class> <class>com.blogspot.na5cent.model.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <shared-cache-mode>NONE</shared-cache-mode> <validation-mode>NONE</validation-mode> <properties> <property name="eclipselink.logging.level" value="FINEST"/> <property name="eclipselink.logging.timestamp" value="false"/> <property name="eclipselink.logging.session" value="false"/> <property name="eclipselink.logging.thread" value="false"/> <property name="eclipselink.logging.parameters" value="true"/> <property name="eclipselink.cache.shared.default" value="false"/> <property name="eclipselink.target-server" value="SunAS9"/> <property name="eclipselink.weaving" value="static"/> </properties> </persistence-unit> <!-- hibernate --> <persistence-unit name="HIBERNATE_PU" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>jdbc/hippo</jta-data-source> <class>com.blogspot.na5cent.model.BinaryFullTextEntry</class> <class>com.blogspot.na5cent.model.DocumentFullTextEntry</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/> <property name="hibernate.search.default.directory_provider" value="filesystem"/> <property name="hibernate.search.default.indexBase" value="${hibernate.search.default.indexBase}"/> <property name="hibernate.search.default.exclusive_index_use" value="false"/> <property name="hibernate.search.default.locking_strategy" value="native"/> </properties> </persistence-unit> </persistence>ส่วน Service ที่ต้องใช้ Hibernate เราก็ Inject EntityManager เข้ามา จากนั้นก็กำหนด PersistenceUnitName เป็น Hibernate(HIBERNATE_PU) ครับ ดังนี้
... ... ... @Service @Transactional(propagation = Propagation.REQUIRED) public class FullTextSearchServiceImpl implements FullTextSearchService { private static final String HTML_START = "<span class=\"fulltext-highlight\">"; private static final String HTML_END = "</span>"; private static final String SEARCH_ON_FIELD = "fullText"; private static final Version LUCENE_VERSION = Version.LUCENE_36; @PersistenceContext(unitName = "HIBERNATE_PU") //**************** private EntityManager entityManager; @Override public PageResult<FullTextSearchResult> search(String keyword, int start, int pageSize, Class<? extends FullTextEntry> clazz) throws Exception { FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); SearchFactory searchFactory = fullTextEntityManager.getSearchFactory(); // QueryBuilder queryBuilder = searchFactory.buildQueryBuilder() .forEntity(clazz) .get(); ... ... ... } }หวังว่าคงเป็นประโยชน์สำหรับบางคนน่ะครับ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น