Java DAO模式+JNDI数据源+CDI和MyBatis

Java DAO模式+JNDI数据源+CDI和MyBatis,java,hibernate,jpa,mybatis,ibatis,Java,Hibernate,Jpa,Mybatis,Ibatis,我计划从我的项目中删除JPA Eclipselink,并使用MyBatis代替它。我在寻找一些不错的指南,在EE容器状态类会话ejb和JNDI数据源+DAO模式+CDI中使用MyBatis的最佳实践是什么?我不使用Spring!。不幸的是,我没有找到任何关于它的好文档 有没有任何方法可以在没有xml配置文件的情况下初始化MyBatis并使用JNDI数据源 MyBatis实现DAO模式并使用CDI将DAO类注入无状态EJB的最佳方式是什么 我使用Java8+Glassfish Payara EE服

我计划从我的项目中删除JPA Eclipselink,并使用MyBatis代替它。我在寻找一些不错的指南,在EE容器状态类会话ejb和JNDI数据源+DAO模式+CDI中使用MyBatis的最佳实践是什么?我不使用Spring!。不幸的是,我没有找到任何关于它的好文档

有没有任何方法可以在没有xml配置文件的情况下初始化MyBatis并使用JNDI数据源

MyBatis实现DAO模式并使用CDI将DAO类注入无状态EJB的最佳方式是什么

我使用Java8+Glassfish Payara EE服务器+MyBatis 3.4.2

更新-1

我按照这一页上的说明做了,但它对我不起作用

这是Glassfish的运行时异常,实际上它是Payara应用程序服务器:

[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类:

@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
也许我犯了个错误,我忘了什么

更新-2

如果至少有一个适当的CDIBean未使用,则Weld不会检测映射器。Servlet不是合适的CDIBean。 解决方法是使用@Dependent注释servlet。
您可以找到更多详细信息。

是的,有一种在JavaEE环境中使用myBatis的好方法,尤其是CDI

有一个mybatis cdi扩展,可以为您解决许多问题,并确保完美的集成。网站及其链接

你应该仔细阅读这本书。特别是在介绍之后,左边菜单中的入门部分。他们解释如何设置一切


此外,还有一个很好的示例项目。这里甚至有一个。

我的答案,为了清晰起见,还报告了我的评论

不是第一个问题,但可能是下一个问题:至少在类路径中需要mybatis-configuration.xml来定义transactionManager和引用jndi数据源

以防万一,为MyBatisSQLSessionFactory添加一个带有日志的默认构造函数。应该只实例化一次

对于WAR,beans.xml必须在WEB-INF中。否则,在单独的依赖项ejb.jar中提取业务代码,所有这些都打包在EAR中

我建议激活:填充beans.xml

I@Inject@SessionFactory保护的SqlSession会话;在EJB中,然后在其方法中:新的DAOsession;因为事务是在EJB级别上管理的,而使用会话注入DAO并没有按预期工作


当调用多个语句时,还要注释EJB方法@TransactionalExecutionType=ExecutionType.REUSE。这将使用相同的接头;对所有交易报表执行一次操作,并只准备一次唯一的报表。先试试,不要弄清楚。

首先,你使用的是什么版本的Java EE?我在原始文章中添加了此信息。不是第一期,但可能是下一期:至少在类路径中需要mybatis-configuration.xml来定义transactionManager和引用jndi数据源。这是我的第一个计划,但mybatis cdi尚未发布。我已经阅读了一些关于如何创建SQLSessionFactory的文档,据我所知,我有两种方法:我可以在生产中使用mybatis cdi beta6,还是您建议我使用第一种解决方案?你能给我举一个如何在实践中使用mybatis cdi的例子吗?我不知道在我的第二个场景中需要注入什么。尚不清楚如何在应用服务器环境中使用容器管理的事务。我不想手动执行sqlSessionFactory.openSession.commit。如果我想使用容器管理的事务,那么我需要向dao实现注入什么?在这种情况下,我似乎需要注入与SqlSessionFactory对象不同的东西。如果需要myBatis,我会使用它。我用得很好。事务部分只需要启用一个CDI拦截器:我可能不理解您所说的第二个场景是什么意思。我的mybatis CDI beta3在生产中运行良好。I@Inject@SessionFactory保护的SqlSession会话;在EJB中,然后在其方法中:新的DAOsession;因为事务是在EJB级别上管理的,并且使用会话注入DAO没有按预期工作;凉的但我并没有预见到任何集成,我已经使用了很长时间的beta版似乎足够稳定,可以满足我的需求。无论如何,我很快就会给它做个测试。