2017-02-14 63 views
0

我打算從我的項目中刪除JPA(Eclipselink),並使用MyBatis代替它。我正在尋找一些很好的指南在EE容器(statelass session ejb)和JNDI數據源+ DAO模式+ CDI(我沒有使用Spring!)中使用MyBatis的最佳實踐是什麼。不幸的是,我還沒有找到任何有關它的好文檔。DAO模式+ JNDI datasouce + CDI與MyBatis

是否有任何方式來初始化MyBatis並使用JNDI數據源而不使用xml配置文件?

什麼是最好的MyBatis的方式來實現DAO模式,並與CDI注入我的DAO類無狀態EJB?

我使用Java 8 + Glassfish(Payara EE服務器)+ MyBatis 3.4.2。


UPDATE-1

我跟着http://www.mybatis.org/cdi/getting-started.html此頁面上的指令,但它並沒有爲我工作。

這是運行時異常我用Glassfish的有(實際上它是一個似鯖水狼牙魚)應用服務器:

[2017-02-14T22:02:23.715+0100] [Payara 4.1] [INFO] [AS-WEB-GLUE-00172] [javax.enterprise.web] [tid: _ThreadID=101 _ThreadName=admin-listener(6)] [timeMillis: 1487106143715] [levelValue: 800] [[ 
    Loading application [mybatis-demo-1.0#mybatis-demo-war-1.0.war] at [/demo]]] 

[2017-02-14T22:02:23.770+0100] [Payara 4.1] [INFO] [] [javax.enterprise.system.core] [tid: _ThreadID=101 _ThreadName=admin-listener(6)] [timeMillis: 1487106143770] [levelValue: 800] [[ 
    mybatis-demo-1.0 was successfully deployed in 1,526 milliseconds.]] 

[2017-02-14T22:03:00.333+0100] [Payara 4.1] [INFO] [] [javax.enterprise.web] [tid: _ThreadID=25 _ThreadName=http-listener-1(2)] [timeMillis: 1487106180333] [levelValue: 800] [[ 
    WebModule[null] ServletContext.log():Marking servlet a.b.war.HelloServlet as unavailable]] 

[2017-02-14T22:03:00.334+0100] [Payara 4.1] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=25 _ThreadName=http-listener-1(2)] [timeMillis: 1487106180334] [levelValue: 900] [[ 
    StandardWrapperValve[a.b.war.HelloServlet]: Allocate exception for servlet a.b.war.HelloServlet 
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type PersonMapper with qualifiers @Default 
    at injection point [BackedAnnotatedField] @Inject private a.b.war.HelloServlet.personMapper 
    at a.b.war.HelloServlet.personMapper(HelloServlet.java:0) 

這是我的測試Servlet:

@WebServlet("/servlet") 
public class HelloServlet extends HttpServlet { 
    @Inject 
    private PersonMapper personMapper; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     response.getWriter().println(personMapper.getPerson(1L).toString()); 
    } 

我的映射類:

@Mapper 
public interface PersonMapper { 
    @Select("SELECT * FROM person WHERE id = #{id}") 
    Person getPerson(@Param("id") long id); 
} 

似乎MyBatisSQLSessionFactory.getSqlSessionFactory()方法不會被調用因爲我在日誌文件中看不到任何東西。

我的SessionFactory類:

public class MyBatisSQLSessionFactory { 
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBatisSQLSessionFactory.class); 

    @Produces 
    @ApplicationScoped 
    @SessionFactoryProvider 
    public SqlSessionFactory getSqlSessionFactory() throws IOException { 
     LOGGER.info("MyBatis is initializing..."); 
     String resource = "mybatis-configuration.xml"; 
     InputStream inputStream = Resources.getResourceAsStream(resource); 
     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
     LOGGER.info("MyBatis has been initialized, SQL Session Factory: {}", sqlSessionFactory.toString()); 
     return sqlSessionFactory; 
    } 
} 

最後我戰爭的結構:

*.war 
│ index.html 
│ 
├───META-INF 
│ │ bean.xml 
│ │ MANIFEST.MF 
│ │ 
│ └───maven 
│   ... 
│ 
└───WEB-INF 
    ├───classes 
    │ └───a 
    │  └───b 
    │   └───war 
    │    │ HelloServlet.class 
    │    │ 
    │    └───mybatis 
    │     │ MyBatisSQLSessionFactory.class 
    │     │ 
    │     └───dao 
    │       PersonMapper.class 
    │ 
    └───lib 

也許我犯了一個錯誤,我忘了什麼事......


UPDATE-2

「如果沒有至少一個適當的CDI bean使用,Weld不會檢測映射器。而Servlet不是正確的CDI bean。 解決方法是@Dependent來註釋的servlet。」 你可以找到更多的細節here

+0

首先您使用的是哪個版本的Java EE? –

+0

我將此信息添加到原始帖子。 – zappee

+0

不是第一個問題,但可能是下一個問題:在classpath中至少需要mybatis-configuration.xml來定義transactionManager和引用jndi dataSource。 – blackwizard

回答

0

是的,有在Java EE的環境不受與MyBatis的一個工作的好方法,尤其是CDI。

有一個MyBatis的-CDI擴展,解決了很多的問題,爲您和確保完美無瑕的集成。該GitHub repository is here並將其鏈接到official documentation.

你應該。尤其是「入門」部分(仔細閱讀official documentation在左邊的菜單,剛過介紹),他們解釋如何設置一切。

此外,還有一個很好的示例項目to be found on GitHub。甚至有一個example with JSF used

+0

這是我的第一個計劃,但mybatis-cdi也沒有發佈。我已閱讀有關如何創建SqlSessionFactory的一些文件,並按照我的理解,我有兩個途徑:https://gist.githubusercontent.com/zappee/b837c389d81a8e658dd362b970e16fc9/raw/eeb4230a5b8b63d602a3118202708136b9b328d6/gistfile1.txt – zappee

+0

我可以使用的MyBatis-CDI beta6生產或者你建議我使用第一種解決方案? 你能給我一個例子如何在實踐中使用mybatis-cdi嗎?我不知道我需要在第二種情況下注入什麼。 不清楚如何在應用程序服務器環境中使用容器管理事務。我不想手動執行sqlSessionFactory.openSession()。commit()。 如果我想使用容器管理事務,那麼我需要注入到我的Dao實現中?在那種情況下,我覺得我需要注入一些不同於SqlSessionFactory對象的東西。 – zappee

+0

如果需要myBatis,我會使用它。我用它很好。事務部分只需要啓用一個CDI攔截器:http://www.mybatis.org/cdi/transactions.html 我可能不明白你的意思是第二種情況。 – 2017-02-14 12:22:55

1

我的答案在這裏,也清楚地報告我的意見。

不是第一個問題,但可能是下一個問題:在classpath中至少需要mybatis-configuration.xml來定義transactionManager和引用jndi dataSource。

以防萬一爲MyBatisSQLSessionFactory添加一個默認構造函數和日誌。應僅實例化一次。

對於WAR,beans.xml必須位於WEB-INF中。否則,將業務代碼提取到單獨的依賴項ejb.jar中,全部打包在EAR中。

我建議激活JTA Transactions:填入beans.xml。

I @Inject @SessionFactory protected SqlSession session;在EJB中,然後在其方法中:new DAO(session);,因爲事務是在EJB級別上管理的,注入會話的注入DAO未按預期工作。

當有多個語句調用時,還會註釋EJB方法@Transactional(executorType=ExecutorType.REUSE)。這將使用相同的連接;所有的交易陳述都只能提供一次,而且只能編寫一次獨特的陳述首先嚐試不弄清楚。

+0

mybatis-cdi-1.0.0發佈;) – zappee

+0

酷!但沒有預見到我的整合,我長期以來一直使用的beta似乎足夠穩定以滿足我的需求。無論如何,我會很快進行測試。 – blackwizard