MyBatis как более быстрая альтернатива Hibernate

В Java сообществе Hibernate framework де-факто считается стандартом для удобной работы с базой данных. Разработчику трудно выбрать другой фреймфорк, потому что порой он не знает о существовании альтернатив. В этой статье я проведу курс молодого бойца по работе с MyBatis framework. Полностью охватить весь framework не получится, но информации будет достаточно, что бы увидеть преимущества и слабые стороны данного framework'а и начать работать с MyBatis.

MyBatis не реализует JPA спеки, а является альтернативой JPA. Основное отличие MyBatis от Hibernate — это то как производится мапинг объектов. Hibernate мапит таблицы БД на сущности, давая нам доступ к данным. Для получения данных Hibernate генерирует SQL запросы, а генерируемые запросы хороши до поры — до времени, а потом они съедают кучу времени, становятся громоздкими и не управляемыми. MyBatis мапится не на таблицы, а на SQL запросы, за формирование запросов отвечает разработчик и только от него будет зависеть как быстро будет работать приложение.

С преамбулой закончили, теперь можно перейти непосредственно к созданию небольшого проекта с использованием MyBatis, что бы познакомиться с ним поближе. Не буду оригинальным, сделаем пару запросов к БД с использованием MyBatis. В примере буду использовать СУБД MySQL, а вы можете использовать любую другую СУБД, которая вам по душе.

Создадим БД mybatis:

CREATE DATABASE `mybatis`;

Создадим таблицы subscriber, tariff, payments:

subscriber:

CREATE TABLE `mybatis`.`subscriber` (
`id` INT( 10 ) NOT NULL ,
`name` VARCHAR( 255 ) NOT NULL ,
`ref_tariff` VARCHAR( 10 ) NOT NULL ,
PRIMARY KEY ( `id` ) 
) ENGINE = MYISAM

tariff:

CREATE TABLE `mybatis`.`tariff` (
`id` INT( 10 ) NOT NULL ,
`descr` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` ) 
) ENGINE = MYISAM

payments:

CREATE TABLE `mybatis`.`payments` (
`id` INT( 10 ) NOT NULL ,
`ref_subscriber` INT( 10 ) NOT NULL ,
`summa` INT( 10 ) NOT NULL ,
PRIMARY KEY ( `id` ) 
) ENGINE = MYISAM

Самое скучное позади — у нас есть БД, из которой мы будем получать данные, теперь приступим непосредственно к работе с MyBatis. Для начала нам необходима библиотека MyBatis. Для получения библиотеки мы будем использовать maven, необходимо добавить зависимость в настройки проекта(pom.xml):

<dependency> 
    <groupId>org.mybatis</groupId> 
    <artifactId>mybatis</artifactId> 
    <version>3.2.8</version> 
</dependency>

На момент написания статьи последняя версия MyBatis 3.2.8

После того как библиотека успешно загрузилась, необходимо настроить подключение к БД. Настройки осуществляются в конфигурационном файле mybatis-config.xml.

Ниже приведен листинг конфигурационного файла:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE configuration 
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-config.dtd"> 
<configuration> 
    <properties resource="config.properties"> <!--ссылка на файл со свойствами(ссылка на СУБД, логин, пароль и тп.)-->
    </properties> 
    <settings><!--в данном блоке можно настроить много параметров. Полный список параметров http://mybatis.github.io/mybatis-3/configuration.html#settings-->
        <setting name="logImpl" value="LOG4J"/> 
    </settings> 
    <environments default="development"><!--в данном блоке настраиваются подключения к БД-->
        <environment id="development"> 
            <transactionManager type="JDBC"/> 
            <dataSource type="POOLED"> 
                <property name="driver" value="${db.driver}"/> 
                <property name="url" value="${db.url}"/> 
                <property name="username" value="${db.username}"/> 
                <property name="password" value="${db.password}"/> 
            </dataSource> 
        </environment> 
    </environments> 
    <mappers><!--в данном блоке необходимо описать маперы, которые используются в проекте-->
        <mapper class="kz.jazzsoft.mapper.SubscriberMapper"/> 
        <mapper class="kz.jazzsoft.mapper.TariffMapper"/>
        <mapper class="kz.jazzsoft.mapper.PaymentMapper"/>
    </mappers> 
</configuration>

В листинге выше я указал 3 мапера — все взаимодействие с БД будет осуществляться через маперы и чем детальнее вы будете понимать как работать с маперами и формировать запросы, тем более производительней будут ваши приложения.

Для корректной работы с MyBatis необходимо создать интерфейс мапера в котором будут предопределены методы, которые будут использоваться и xml файл настроек в котором будут описаны sql запросы, правила их мапинга на объекты и тп.

Создадим интерфейс kz.jazzsoft.mapper.SubscriberMapper:

package kz.jazzsoft.mapper;

import kz.jazzsoft.dal.Subscriber;

public interface SubscriberMapper {

Subscriber getSubscriberById(Integer id);

List getSubscriber();

}

В данном интерфейсе мы определили два метода:

1. getSubscriberById — вернет одного пользователя по id;

2. getSubscriber — вернет список пользователей;

Но что бы данные методы заработали необходимо создать xml маппер с sql запросами.

<!DOCTYPE mapper     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kz.jazzsoft.mapper.SubscriberMapper">
    <select 
id="getSubscriberById" <!--название метода-->
parameterType="java.lang.Integer" <!--тип входящих параметров, может быть поистине разнообразным, начиная от Map и заканчивая EntityBean.--> 
>
        select * from subscriber where id = #{id}  <!-- поле в фигурных скобках это параметр, который прилетел в метод. Если это Map — то {имя} это ключ к переменной. Если в метод передаем EntityBean то {имя} — это название переменной данного bean.-->
    </select>
    
    <select id="getSubscriber">
        select * from subscriber
    </select>
</mapper>

Я упустил еще один момент, который необходимо было сделать — это создать классы beanEntity, на которые мы будем мапить результаты выполнения запросов.

Subscriber:

package kz.jazzsoft.dal;
import java.util.List;
public class Subscriber {
    private Long id;
    private String name;
    private Tariff tariff;
	private List<Payment> payments
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Tariff getTariff() {
        return tariff;
    }
    public void setTariff(Tariff tariff) {
        this.tariff = tariff;
    }
    public List<Payment> getPayments() {
        return paymentList;
    }
    public void setPayments(List<Payment> payments) {
        this.payments = payments;
    }
    public List<Connection> getConnections() {
        return connections;
    }
}

Tariff:

package kz.jazzsoft.dal;
public class Tariff {
    private Long id;
    private String descr;
   
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getDescr() {
        return descr;
    }
    public void setDescr(String descr) {
        this.descr = descr;
    }
}

Payment:

package kz.jazzsoft.dal;
public class Payment {
    private Long id;
    private Integer summa;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Integer getSumma() {
        return discount;
    }
    public void getSumma(Integer summa) {
        this.summa = summa;
    }
}

Можно сразу посмотреть, как работает код, для этого необходимо подключиться к БД и инициализировать нужный мапер, а пока он у нас один (SubscriberMapper). Создадим класс, в котором будем работать:

Work:

package kz.jazzsoft;
import kz.jazzsoft.mapper.SubscriberMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
public class Work {
    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory;
        SubscriberMapper subscriberMapper;
        Reader reader = null;
        try {
            reader = Resources
                    .getResourceAsReader("mybatis-config.xml"); //Читаем файл с настройками подключения и настройками MyBatis
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            subscriberMapper = sqlSessionFactory.openSession().getMapper(SubscriberMapper.class); //Создаем маппер, из которого и будем вызывать методы getSubscriberById и getSubscribers
List<Subscriber> subscribers = subscriberMapper.getSubscribers();
Subscriber subscriber = subscriberMapper.getSubscriberById(101);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Запросы выполнились и у нас есть объекты, с которыми мы можем работать. Вы можете посмотреть, что у объектов есть id и другие поля заполнены, но не все. Тут есть один нюанс, если колонка в БД имеет такое же имя как переменная, то она автоматически смапиться на нее. Что бы расширить возможности мапинга и создавать сложные структуры в арсенале MyBatis есть тег ResultMap, который позволяет настраивать произвольный мапинг. Делать связи one-to-one и one-to-many.

ResultMap представляет из себя описание правил связи полей EntityBean с колонками из таблиц. Пример для Subscriber:

<resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber">
        <id property="id" column="id"/>
        <result property="name" column="name"/> <!--можно поменять поле name в Subscriber и посмотреть результат, соотвественно поменяв свойство property-->
</resultMap>

В итоге маппер для Subscriber будет выглядеть следующим образом:

<!DOCTYPE mapper     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kz.jazzsoft.mapper.SubscriberMapper">
<resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
</resultMap>
    <select id="getSubscriberById" parameterType="java.lang.Integer"
resultMap="subscriber">  <!-- ссылка на ResultMap по которому и будет происходить мапинг-->
        select * from subscriber where id = #{id}
    </select>
    
    <select id="getSubscribers" resultMap="tariff">
        select * from subscriber
    </select>
</mapper>

Связь one-to-one осуществляется не сложнее примера выше. Но нам сначала необходимо будет описать следующий мапер Tariff. Через него мы будем получать данные для связанного поля в Subscriber.

Создаем сущность Tariff:

package kz.jazzsoft.dal;
public class Tariff {
    private Long id;
    private String descr;
   
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getDescr() {
        return descr;
    }
    public void setDescr(String descr) {
        this.descr = descr;
    }
}

Создаем интерфейс мапера TariffMapper, нам понадобится только один метод:

package kz.jazzsoft.mapper;
import kz.jazzsoft.dal.Tariff;
public interface TariffMapper {
    Tariff getTariffById(Integer id);
}

Создаем мапер:

<!DOCTYPE mapper     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kz.jazzsoft.mapper.TariffMapper">
    <resultMap id="tariff" type="kz.jazzsoft.dal.Tariff">
        <id property="id" column="id"/>
        <result property="descr" column="descr"/>
    </resultMap>
    <select id="getTariffById" resultMap="tariff" parameterType="java.lang.Integer">
        select * from tariff where id = #{id}
    </select>
</mapper>

Теперь можно добавить Subscriber c Tariff в SubscriberMaper, в resultMap необходимо добавить правило связи:

<resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <association 
		property="tariff"  <!--свойство в Subscriber -->
		column="ref_tariff"  <!-- колонка в таблице Subscriber, по которой собственно и будет происходить связь с нужным тарифом-->
                    	javaType="kz.jazzsoft.dal.Tariff"  <!--описание типа, который у нас будет возвращаться-->
                     	select="kz.jazzsoft .mapper.TariffMapper.getTariffById"  <!-- Тут у нас работа передается тарифному мапперу, который выполнит sql и замапит все согласно своим настройкам.-->
                     	fetchType="eager"  <!-- Тип запроса--> />
</resultMap>

Необходимо заменить данный resultMap и можно будет узнать на каком тарифном(Tariff) плане у нас находится Абонент(Subscriber)

Subscriber.gettariff().getDescr();

Добавим к Абоненту(Subscriber) список его платежей(Payments)(one-to-many):

Для начала необходимо создать EntityBean Payment:

package kz.jazzsoft.dal;
public class Payment {
    private Long id;
    private Integer summa;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Integer getSumma() {
        return discount;
    }
    public void getSumma(Integer summa) {
        this.summa = summa;
    }
}

Теперь необходимо создать интерфейс мапера PaymentMapper, он будет простой. Только один метод получения списка платежей по id пользователя.

package kz.jazzsoft.mapper;
import kz.jazzsoft.dal.Payment;
import java.util.List;
public interface PaymentMapper {
    List<Payment> getPaymentsByIdSub(Integer id);
}

Необходимо создать xml мапер:

<!DOCTYPE mapper     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kz.jazzsoft.mapper.PaymentMapper">
    <resultMap id="payment" type="kz.jazzsoft.dal.Payment">
        <id property="id" column="id"/>
        <result property="summa" column="date"/>
    </resultMap>
    <select id="getPaymentsByIdSub" resultMap="payment" parameterType="java.lang.Integer">
        select * from payment where ref_subscriber = #{id}
    </select>
</mapper>
Свяжем список платежей (payment) с абонентом (Subscriber):

<source lang="xml">
<resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="tariff" column="ref_tariff"
                    	javaType="kz.jazzsoft.dal.Tariff"
                     	select="kz.jazzsoft.mapper.TariffMapper.getTariffById"	fetchType="eager"/>
        <collection 
			property="payments" <!--свойство в bean Subscriber-->
			column="id" <!--id Subscriber--> 
			javaType="List" <!--тип который получим на выходе(список)-->
			ofType="Payment" <!--а этим типом будет заполнен список-->
			select="kz.jazzsoft.mapper.PaymentMapper.getPaymentsByIdSub" <!-- метод, который необходимо выполнить, что бы получить список платежей по id Абонента-->
            fetchType="eager" <!--тип запроса-->             
            />
</resultMap>

Полученный resultMap заменяем в SubscriberMapper и можно посмотреть все платежи пользователя. Но на этом все самое интересное только начинается.

MyBatis имеет функционал, который позволяет формировать sql запросы динамически в зависимости от параметров, которые были в него переданы. Например нам нет необходимости создавать кучу sql на каждое действие(выборки из одной таблицы, но по разным параметрам), можно отделаться одним методом, который будет фильтровать тех же абонентов по нескольким колонкам или вообще не будет фильтровать и вернет всех в зависимости от входных данных, но обо всем по порядку.

Для динамического формирования SQL запросов в арсенале MyBatis имеется достаточно компонентов для решения большинства задач. Рассматривать все мы не будем, так как их достаточно много и их можно комбинировать и тп. Для примера расмотрим IF оператор, больше информации можно прочитать в официальном руководстве: mybatis.github.io/mybatis-3/dynamic-sql.html

IF Оператор:

<select id="getSubscribersWithParam" parameterType="map">
	select * from subscriber where (1=1)
	<if test="descr != null" >
		and decr = #{descr}
	</if>
</select>

В запросе приведенном выше выполняется проверка, на то что объект в Map по ключу descr не null, тогда в запрос будет добавлена строка в блоке if и таких блоков может быть сколько угодно, они могу быть вложенными.

<update id="updateSubscriber" parameterType="kz.jazzsoft.dal.Subscriber">
	udpate subscriber
    	<set>
		<if test="descr != null">
			descr = #{descr},
        </if>
   	 </set>
	where id = #{id}
</update>


MyBatis при разумном использовании может дать ощутимый прирост в скорости работы приложения. Может показаться страшно писать самому запросы и правила мапинга, но это только кажется, Hibirnate тоже не так уж прост.

Не существует одного универсального решения, которое подошло бы всем, в каждом выборе нужен четкий расчет. MyBatis можно использовать совместно с Hibernate там где это действительно нужно, а это сможете определить только вы.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 39
  • +2
    Меня в Java всегда отталкивала ее многословность, если можно так выразиться. Я понимаю, что это расплата за статичную типизацию и возможность контроля на этапе компиляции. Но созерцание таких xml-конфигураций несколько угнетает.

    Сам сейчас пытаюсь перейти на Java, как основной язык для заработка. И это — один из моментов, которые меня напрягают больше всего. Я сам стороннок статичной типизации, но всего должно быть в меру.

    В этом плане Scala выглядит попривлекательнее из-за автоматического выведения типов и автогенерации геттеров и сеттеров по анотациям. Но от подобных конфигов она все равно не спасает.

    Простите, накипело.

    А статья хорошая. Действительно, в подавляющем большинстве учебных материалов, которые я читал рассказывалось о Hibernate, а про альтернативы ни слова. Новичку в разнообразии библиотек, которые есть для Java сориентироваться очень сложно. Тем более не зная, что искать.

    Спасибо автору, будет чем заняться на выходных.
    • +3
      Но созерцание таких xml-конфигураций несколько угнетает.
      Hibernate сконфигурировать можно и программно.
      автогенерации геттеров и сеттеров по анотациям
      Для java есть такие плюшки для этого.

      Хотя, в статье вроде как не про Java, а конкретно про громоздкость и медленность Hibernate речь идёт )
      • +4
        Hibernate сконфигурировать можно и программно

        MyBatis тоже, доки. Лично я не понимаю желание автора использовать XML там, где у него абсолютно нет преимуществ.
        • –4
          Если делать программно, то для изменения конфигурации необходимо перекомпилить приложение?
          • +1
            Вот вам вопросы:
            1. Часто ли вы подсовываете xml в jar?
            2. Что мешает скомпилировать класс с зависимостями(обычно 1, Idea к примеру хорошо определяет что-компилировать)?
          • 0
            -
            • 0
              Эта статья не претендовала на исчерпывающий мануал по MBatis, а для того что бы показать общие идеи MyBatis, XML подходит как нельзя лучше.
              • –1
                У каждого из методов конфигурации есть свои плюсы и минусы, что у xml, аннотаций или программной реализации.

                В данном случае плюсами и смыслом xml в том что:
                во-первых, она (конфигурация) находится в одном месте (в не скольких xml-файлах), а не размазана по десяткам классов
                во-вторых, если xml вынести за пределы ear/war/jar, то появляется возможность менять конфигурацию
            • +5
              Почитайте про Spring Data. Там просто объявляется интерфейс, а Spring по названию метода может сам сгенерировать запросы. В случае сложных запросов — можно написать их на JPQL. github.com/spring-projects/spring-data-jpa-examples/blob/master/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/simple/SimpleUserRepository.java
              • 0
                буквально сорвали с языка про Spring Data, а в частности, про Spring Data JPA
              • –1
                Попробуйте kotlin.
                • 0
                  Пожалуйста, аргументируйте свои минуса. Я же не призываю использовать только kotlin, у каждого есть свое мнения и свой выбор, я просто предложил как вариант и все.
                • +2
                  Сам сейчас пытаюсь перейти на Java, как основной язык для заработка.


                  Планируете стать Java-заработчиком?
                  • 0
                    Да, в процессе обучения.
                  • 0
                    автогенерации геттеров и сеттеров по анотациям

                    какой такой анатация? их компилятор без анотаций выводит
                  • +5
                    Статья как руководство к MyBatis довольно неплохая, автору спасибо! Но не могу таки согласиться, что MyBatis это альтернатива Hibernate. Альтернативы Hibernate это EclipseLink, DataNucleus, а MyBatis это таки своеобразная библиотека для маппинга объектов.
                    • 0
                      Вычеркните EclipseLink, с ним с завидной периодичностью возникают разнообразные проблемы.
                      Тоже накипело, как у автора первого комментария.
                      • +2
                        OpenJPA забыли)
                      • +4
                        Хотелось бы реально бенчмарки увидеть и услышать про проекты, где всё упёрлось именно в «медленность» Hibernate. Я не спорю, что у него оверхед есть, но не сталкивался с ситуации, когда это становилось слабым звеном в системе.

                        btw, если уж у вас проблема именно со скоростью Hibernate, то используйте чистый JDBC )
                        • 0
                          Автор скорее всего имел ввиду тюннинг SQL запросов
                          • +4
                            Это как раз странно, так как Hibernate вполне себе поддерживает и нативные запросы и HQL — обтюнингуйся в узких местах.
                          • –2
                            Ситуаций когда Hibernate становится слишком меделнным — вполне достаточно. Например если вам нужно работаеть не с парой-десятком объектов, а с «пачками» на много тысяч. И использовать DB-specific SQL. Но обычно если такие ситуации и возникают, то от ORM чаще всего отказываются совсем и спользуют либо чистый SQL, либо что-то вроде JOOQ.
                            • 0
                              Ответ на ваш вопрос есть в докладе
                              1. youtu.be/1KphwODu1gg
                              2. youtu.be/YzOTZTt-PR0

                              Overhead у него значительный все же.
                              Я вообще практикую использование dto c чистым sql, на мой взгляд это более правильное решение если система нагруженная.
                            • +1
                              Использовали MyBatis на несколько больших проектов. Только хорошие впечатления.

                              Из того что не указал автор — возможность создание TypeHandler'ов. Простой пример — в Java есть Enum со списком значений и нужно его замапить на значения из колонки. Создаётся TypeHandler — класс, который отвечает за преобразования этого объекта из Java в СУБД и наоборот, прописывается в маппинге запроса и всё. Дальше при выполнении запроса получает типизированные объекты. Мы использовали TypeHandler'ы для структур, списка структур, Enum'ов (шаблонный TypeHandler).

                              Также маппинги можно прописывать в интерфейсе (не скажу что это всегда удобно, но по крайней мере есть возможность не использовать xml).

                              Так же для IDEA есть отличный плагин по работе с MyBatis — plugins.jetbrains.com/plugin/7293. Я пробовал разные плагины для MyBatis, но этот оказался самый лучший. Из плюсов — подсветка синтаксиса в xml, autocomlite в xml, автопроверка соответствия интерфейса xml маппингу и наоборот, связывание методов интерфейса с маппингом (можно просто перейти в реализацию метода из интерфейса в xml — как к реализации метода интерфейса в классе). Также если настроить подключение к СУБД в IDEA, работает autocomplite по SQL запросам в xml (Например, если у нас в СУБД есть таблица students то если пишем в xml маппинге SELECT * FROM st и нажимаем Ctrl+Space IDEA подскажет, что можно выбрать таблицу students)

                              P.S. Работали с СУБД Oracle. В основном был вызов хранимых процедур и функций. Но были и select, и update.
                              • 0
                                вы же про @javax.persistence.Enumerated и org.hibernate.type.EnumType знаете, да? ну, т.е. как бы у MyBatis тут нет преимуществ перед прочими. Так же, есть пакет org.hibernate.usertype, в котором есть не только org.hibernate.usertype.UserType
                                и поддержка Hibernate изначально из коробки в IDEA в плане озвученных плюсов к плагину MyBatis
                              • 0
                                А еще автор не написал, что можно в MyBatis`е использовать аннотации, с которыми написание запросов становится просто удовольствием.

                                Выглядит примерно так:

                                public interface EmployeeMapper {

                                Select(«SELECT * FROM employee WHERE id = #{id}»)
                                @ResultMap(«employeeResultMap»)
                                Employee findById(long id);

                                }

                                нужен только один XML-файл для конфига, и все!
                                • 0
                                  В Hibernate вроде как тоже можно запросы аннотациями:

                                  @NamedNativeQueries({
                                  	@NamedNativeQuery(
                                  	name = "findEmployeeCodeNativeSQL",
                                  	query = "select * from employee e where e.id = :id",
                                          resultClass = Employee.class
                                  	)
                                  })
                                  
                                  @Entity
                                  @Table(name = "employee", catalog = "my")
                                  public class Employee implements java.io.Serializable {
                                  ...
                                  
                                  
                                  Query query = session.getNamedQuery("findEmployeeCodeNativeSQL").setString("id", "666");
                                  
                                  • 0
                                    Ну кстати симпатично, а это какая версия Хибернейта?
                                    • 0
                                      Любая, поддерживающая JPA 1.0 — это оттуда аннотация.
                                      • 0
                                        Это вообще JPA спецификация. А на JPA уже версия 2.1 во все поля.
                                  • 0
                                    Без бенчмарков все это как-то голословно.
                                    • 0
                                      Советую также посмотреть в сторону Apache Cayenne. Среди плюсов по сравнению с MyBatis можно назвать построение конечных sql запросов к БД через шаблонизатор Velocity. Получается минимум xml и максимум гибкости.
                                      • –1
                                        Все сказанное в статье про Hibernate — чушь, больше всего доставляет заголовок — «MyBatis как более быстрая альтернатива Hibernate». Нет опыта работы с Hibernate — не пишите про него, зачем портить неплохую статью ничем не подтвержденными сравнениями?! Hibernate может и сам генерировать SQL, а может предоставить это разработчику. Если у автора нет достаточного опыта работы с Hibernate, зачем писать о том, что он медленнее?

                                        «MyBatis мапится не на таблицы, а на SQL запросы»
                                        Hibernate тоже так умеет, но почему-то в статье эта возможность — прерогатива только MyBatis-а

                                        MyBatis при разумном использовании может дать ощутимый прирост в скорости работы приложения
                                        А Hibernate при таком же разумном использовании не может, не?

                                        MyBatis можно использовать совместно с Hibernate там где это действительно нужно
                                        Да ладно, серьезно? Будете на одном проекте два ORM-а разворачивать?
                                        • 0
                                          Из всех ORM больше всего понравилась Avaje Ebean (используется в Play Framework) — простая в использовании, минимум оверхеда, JPA
                                          Всё остальное (тем более Hibernate) показалось слишком громоздким и неудобным.
                                          • 0
                                            К вопросам по ужасным xml, громоздкости, мапингу без xml:

                                            Mybatis поддерживает программное конфигурирование, можно с помощью аннотаций запихнуть весь запрос в интерфейсы. Но есть как минимум две причины по которой мне не очень нравиться использовать аннотации в Mybatis
                                            • Сам sql становиться менее читаемым, аннотация становится мостроподобной. А в xml файле все аккуратно лежит, подсвечивается.
                                            • В интерфейсе было проблематично указать ResultMap для запроса. Когда я только начал использовать аннотации, пришлось несколько раз продублировать ResultMap для каждого метода. Решение было не явным и в документации нигде не описано, что можно использовать уже объявленный ResultMap по имени метода в котором он был объявлен, с суффиксом “-void”(Если ResultMap был объявлен для метода getUsers, дальше данный ResultMap можно будет использовать по имени “getUsers-void”

                                            Использовать или не использовать аннотации и отказываться от xml — это дело вкуса, мне не понравилось писать sql запросы в аннотации.
                                            • 0
                                              К мнению о том, что Hibernate оклеветали, я не компетентен и тп

                                              От части в этом есть смысл. Знания и опыт по Hibernate — у мня не глубоки и подозревал что будет такое мнение. Начал я эту статью писать с того, что необходимо было определить что быстрее и целесообразно ли использовать MyBatis. Я проводил тестирование с помощью labs.carrotsearch.com/junit-benchmarks.html, да и опыта такого не было. Посмотрев на скудность данных и не было уверенности что я все делаю правильно — сравнивать две ORM без большого опыта использования обоих не верно, но на тех тестах которые мной были проведенный(выборка элементарных объектов со связью один к одному и один к многим), показали что Hibernate процентов на 10 уступает MyBatis со Spring (на аннотациях), а если использовать стандартные механизмы мапинга MyBatis то разрыв становится больше.

                                              Использовать можно и две ORM на проекте — MyBatis для работы с сложными запросами, т.к. он обрабатывает запросы быстрее, а Hibernate использовать для CRUD(без Read) он прекрасно с этим справляется. — IMHO

                                              Если есть опыт проведения сравнений ORM и других библиотек. прошу поделиться опытом.
                                              • +1
                                                Использовать можно и две ORM на проекте


                                                Вы рискуете не помирить их по транзакциям. Либо же цена этому мирению будет запредел.
                                              • +1
                                                Скажите пожалуйста, а в 2015 году Hibernate все еще желает mutable POJO's? Какие вообще Java ORM фрэймворки поддерживают immutability?

                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.