Вступление
Платформа как услуга (PaaS) заботится об инфраструктуре, промежуточном программном обеспечении, конфигурации и других проблемах, связанных с платформой, от разработчиков и позволяет им сосредоточиться на своей ключевой компетенции, то есть на разработке и разработке своих доменных приложений. В этой статье я собираюсь продемонстрировать, как с минимальными усилиями создать «приложение Polyglot», включающее хранение и поиск данных в RDBMS и NoSQL.
Что такое приложение Polyglot?
В контексте приложений баз данных приложение полиглот включает в себя постоянство нескольких баз данных. Это несложно, когда задействованные бизнес-объекты хранятся в базах данных РСУБД. Все становится сложным, когда эти базы данных неоднородны по своей природе (например, сочетание различных NoSQL и, возможно, также RDBMS). Возьмем, к примеру, случай пользователей, у которых много адресов. Пользователь должен храниться в MongoDB, а адреса должны храниться в RDBMS.
(1-M) User ---------> Address (MongoDB) (MySQL)
Этот вид использования ставит некоторые действительно сложные задачи, такие как:
1. Кривая обучения
Базы данных NoSQL имеют свой собственный API (и есть клиенты высокого уровня). Они имеют длительную кривую обучения, и для их работы обычно требуются разработчики, которые уже имеют опыт работы с ними.
2. Сложность развития
Управление различными бизнес-объектами, которые будут сохранены в гетерогенных системах, представляет собой проблему при разработке на уровне доступа к данным. Ваш код будет использовать разные API, что затруднит разработку, тестирование и поддержку вашего кода.
3. Сложность развертывания
Различные базы данных NoSQL имеют свои собственные настройки, структуру и механизм развертывания. Они должны быть настроены для лучшей производительности и потребностей приложений. Самостоятельное управление этой разнообразной инфраструктурой является сложной задачей с точки зрения затрат и сложности. Поставщик решений должен тратить время на решение бизнес-задач наилучшим образом, а не на решение и борьбу с проблемами, которые ставят эти технологии.
Так что же нам делать?
Первые две из этих проблем могут быть решены с помощью Kundera в качестве библиотеки отображения объектного хранилища данных. Кундера поддерживает постоянство Полиглота и, как мы увидим, это почти не требует усилий для управления различными объектами для разных баз данных. Третья проблема решается с помощью провайдера PaaS. Ваш поставщик PaaS будет отвечать за управление базами данных, аппаратными ресурсами, серверами приложений и т. Д. При разработке приложения. OpenShift от RedHat — это платформа приложений в облаке, где разработчики приложений и команды могут создавать, тестировать, развертывать и запускать свои приложения. OpenShift предоставляет различные «картриджи», которые вы можете добавить в свое приложение в соответствии с вашими потребностями. MongoDB и MySQL среди них. Мы создадим приложение, которое читает и записывает бизнес-объекты в MySQL и MongoDB, используя Kundera.
Давайте готовьтесь
Теперь мы готовы построить наше приложение polyglot, включающее две сущности: User и Address. Пользователь будет храниться в MongoDB, а Адрес в MySQL. Вот шаги, которые вы должны выполнить:
1. Зарегистрируйтесь и войдите в OpenShift .2. Добавить Java-приложение на основе Tomcat 7 (картридж JBoss EWS 2.0) 3. Добавить картриджи — База данных MongoDB Nosql 2.2 и база данных MySQL 5.14. Напишите ваше приложение NoSQL. Вставьте свой код в Git-репозиторий, созданный в OpenShift. (Артефакты развертываются на серверах автоматически) .6. Протестируйте ваше приложение.
Регистрация и вход
1. Посетите веб-сайт https://www.openshift.com/ 2. Нажмите «Зарегистрироваться» и введите данные. Подтвердите и войдите.
Создать приложение
1. Нажмите Мои приложения -> Добавить приложение2. Выберите Java в раскрывающемся списке.3. Нажмите на Tomcat (JBoss EWS 2.0) 4. Дайте вашему приложению имя и нажмите «Создать приложение».
Добавить картриджи
1. Нажмите Мои приложения -> <Имя вашего приложения> 2. Нажмите «Добавить картридж» 3. Добавьте «MySQL Database 5.1 ″, добавляя этот картридж, запишите учетные данные аутентификации базы данных и имя схемы, лучше сделайте снимок экрана) 4. Повторите вышеуказанный шаг для добавления картриджа «База данных MongoDB NoSQL 2.2».
Написать приложение NoSQL
Мы покажем, как написать простое приложение для чтения и записи между хранилищами данных на MySQL и MongoDB.
1. Добавьте зависимости в pom.xml
Add Kundera repositories under repositories tag inside pom.xml:
<repository> <id>sonatype-nexus</id> <name>Kundera Public Repository</name> <url>https://oss.sonatype.org/content/repositories/releases</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>kundera-missing</id> <name>Kundera Public Missing Resources Repository</name> <url>http://kundera.googlecode.com/svn/maven2/maven-missing-resources</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository>
Add following dependencies under dependencies tag inside pom.xml:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!-- Kundera Dependency --> <dependency> <groupId>com.impetus.client</groupId> <artifactId>kundera-rdbms</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.impetus.core</groupId> <artifactId>kundera-core</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.impetus.client</groupId> <artifactId>kundera-mongo</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency>
2. Напишите классы сущностей
User.java
import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name = "User", schema = "PaaSMongo@mongo-openshift_pu") public class User { @Id @Column(name = "ID") private int id; @Column(name = "NAME") private String name; @Column(name = "AGE") private int age; @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "ADDRESS_ID") private Address address; //Getters and setters omitted }
Address.java
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "ADDRESS", schema = "PaaSMongo") public class Address { @Id @Column(name = "ADDRESS_ID") private String addressId; @Column(name = "STREET") private String street; //Getters and setters omitted }
3. Напишите persistence.xml
<persistence 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 https://raw.github.com/impetus-opensource/Kundera/Kundera-2.0.4/kundera-core/src/test/resources/META-INF/persistence_2_0.xsd" version="2.0"> <!-- Persistence Units for Twitter application --> <persistence-unit name="mongo-openshift_pu"> <provider>com.impetus.kundera.KunderaPersistence</provider> <class>com.impetus.kundera.mongo.entities.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="kundera.nodes" value="127.5.210.1" /> <property name="kundera.port" value="27017" /> <property name="kundera.keyspace" value="PaaSMongo" /> <property name="kundera.dialect" value="mongodb" /> <property name="kundera.client.lookup.class" value="com.impetus.client.mongodb.MongoDBClientFactory" /> <property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider" /> <property name="kundera.cache.config.resource" value="/ehcache-test.xml" /> <property name="kundera.username" value="admin" /> <property name="kundera.password" value="eaGbuGfS1ct4" /> </properties> </persistence-unit> <persistence-unit name="rdbms-openshift_pu"> <provider>com.impetus.kundera.KunderaPersistence</provider> <class>com.impetus.kundera.mongo.entities.Address</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql://127.5.210.1:3306/PaaSMongo" /> <property name="hibernate.connection.username" value="adminlRwnUcy" /> <property name="hibernate.connection.password" value="jvsq6w131Y1p" /> <property name="kundera.client.lookup.class" value="com.impetus.client.rdbms.RDBMSClientFactory" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence>
4. Напишите web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="false"> <listener> <listener-class>com.impetus.kundera.mongo.listener.StartUpListener</listener-class> </listener> </web-app>
5. Напишите CRUD-операции
OperationHandler.java
import java.util.List; import com.impetus.kundera.mongo.entities.User; public interface OperationHandler { void saveUser(User user); User findUserById(Class clazz, Object id); List<User> findUserByName(String clazz, String name); List<User> findUserByAge(String clazz, int age); List<User> findAllUser(String clazz); }
OperationHandlerImpl.java
import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.impetus.kundera.mongo.entities.User; public class OperationHandlerImpl implements OperationHandler { private EntityManagerFactory emf; private EntityManager em; @Override public void saveUser(User user) { getEntityManager(); em.persist(user); } @Override public User findUserById(Class clazz, Object id) { getEntityManager(); return em.find(User.class, id); } @Override public List<User> findUserByName(String clazz, String name) { getEntityManager(); Query q = em.createQuery("Select u from " + clazz + " u " + "where u.name = " + name); return q.getResultList(); } @Override public List<User> findUserByAge(String clazz, int age) { getEntityManager(); Query q = em.createQuery("Select u from " + clazz + " u " + "where u.age = " + age); return q.getResultList(); } @Override public List<User> findAllUser(String clazz) { getEntityManager(); Query q = em.createQuery("Select u from " + clazz + " u "); return q.getResultList(); } private EntityManager getEntityManager() { if (emf == null) { emf = Persistence .createEntityManagerFactory("mongo-openshift_pu,rdbms-openshift_pu"); em = emf.createEntityManager(); } else if (em == null) { em = emf.createEntityManager(); } return em; } public void removeAll(String clazz) { getEntityManager(); Query q = em.createQuery("Delete from " + clazz + " u "); } public void close() { em.close(); emf.close(); } public void clear() { em.clear(); } }
6. Создать Startup Listener
import javax.servlet.ServletContextEvent;</pre> import javax.servlet.ServletContextListener; import com.impetus.kundera.mongo.entities.Address; import com.impetus.kundera.mongo.entities.User; import com.impetus.kundera.mongo.handler.OperationHandlerForUser; public class StartUpListener implements ServletContextListener { OperationHandlerForUser handler = null; int userId1; int userId2; @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent arg0) { handler = new OperationHandlerImpl(); persist(); find(); } private void persist() { Double d = Math.random(); Long t1 = System.currentTimeMillis(); Address address1 = new Address(); address1.setAddressId(t1.toString()); address1.setStreet("AAAAAAA"); Address address2 = new Address(); address2.setAddressId(t1.toString() + "1"); address2.setStreet("BBBBBBB"); User user1 = new User(); userId1 = d.intValue(); user1.setPersonId(d.intValue()); user1.setPersonName("Kuldeep"); user1.setAge(24); user1.setAddress(address1); User user2 = new User(); userId2 = d.intValue() + 1; user2.setPersonId(d.intValue() + 1); user2.setPersonName("Amresh"); user2.setAge(30); user2.setAddress(address2); handler.saveUser(user1); handler.saveUser(user2); handler.clear(); } private void find() { User user1 = handler.findUserById(User.class, userId1); System.out.println(user1.getPersonName()); System.out.println(user1.getAge()); System.out.println(user1.getAddress().getAddressId()); System.out.println(user1.getAddress().getStreet()); User user2 = handler.findUserById(User.class, userId2); System.out.println(user2.getPersonName()); System.out.println(user2.getAge()); System.out.println(user2.getAddress().getAddressId()); System.out.println(user2.getAddress().getStreet()); } }
Push-код и тестовое приложение
1. Скопируйте ваши открытые ключи в операционной системе в Моя учетная запись -> Открытые ключи2. Клонируйте ваш репозиторий git.3. Зафиксируйте код и нажмите.4. Проверьте данные, записанные в базу данных с консоли MySQL и MongoDB, и проверьте вывод, напечатанный в журналах Tomcat.
Вывод
Как мы видим, Kundera + Openshift значительно облегчают разработку и развертывание. Все, что нам нужно, это несколько кликов на веб-странице Openshift и простая настройка в persistence.xml. На самом деле мы сосредоточились на написании сущностей и кода CRUD. Kundera также поддерживает доступ на основе REST для данных, хранящихся в нескольких хранилищах данных. Для этого необходимо добавить запись сервлета JAX-RS в дескриптор развертывания веб-приложения. Это открывает для вас новую возможность представить свои данные различным приложениям.