2017-02-14 55 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