Liran Zelkha has uploaded a new change for review. Change subject: core: WIP: Adding JPA to ovirt ......................................................................
core: WIP: Adding JPA to ovirt This patch will introduce the neccessary infrastructure to use JPA in ovirt. A first candidate, implemented in this patch, will be the VdsGroup entity. The goal is to allow ovirt to enjoy JPA/hibernate capabilities: 1. 1st level caching of multiple queries to the same entity in the same transaction. 2. Lazy loading for large objects (such as VDS, VM, etc). In the future we can explore features like: 1. 2nd level caching (based on Infinispan) 2. Cross-database support Future patches will move additional entities to JPA. Change-Id: I3cd0bbf9f0913955cb3e1facfa9a4bdc1f1ab24d Signed-off-by: [email protected] <[email protected]> --- M backend/manager/modules/common/pom.xml M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VDSGroup.java M backend/manager/modules/dal/pom.xml A backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/GuidMapper.java A backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/HibernateFacade.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsGroupDAODbFacadeImpl.java A backend/manager/modules/dal/src/main/resources/META-INF/persistence.xml A backend/manager/modules/dal/src/test/java/META-INF/persistence.xml M backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VdsGroupDAOTest.java 9 files changed, 246 insertions(+), 6 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/06/22806/1 diff --git a/backend/manager/modules/common/pom.xml b/backend/manager/modules/common/pom.xml index d2dd9ed..c4b098d 100644 --- a/backend/manager/modules/common/pom.xml +++ b/backend/manager/modules/common/pom.xml @@ -47,6 +47,12 @@ <scope>provided</scope> </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-entitymanager</artifactId> + <version>4.3.0.Final</version> + </dependency> + </dependencies> <build> diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VDSGroup.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VDSGroup.java index 6de8a5e..51bffe2 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VDSGroup.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VDSGroup.java @@ -2,8 +2,16 @@ import java.io.Serializable; import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; + +import org.hibernate.annotations.Type; import org.ovirt.engine.core.common.scheduling.OptimizationType; import org.ovirt.engine.core.common.utils.ObjectUtils; import org.ovirt.engine.core.common.validation.annotation.ValidI18NName; @@ -16,10 +24,15 @@ @ValidVdsGroup(groups = { CreateEntity.class }) +@Entity +@Table(name = "vds_groups") public class VDSGroup extends IVdcQueryable implements Serializable, BusinessEntity<Guid>, HasStoragePool<Guid>, Nameable, Commented { private static final long serialVersionUID = 5659359762655478095L; + @Id + @Column(name = "vds_group_id") + @Type(type = "org.ovirt.engine.core.dao.GuidMapper") private Guid id; @NotNull(message = "VALIDATION.VDS_GROUP.NAME.NOT_NULL", groups = { CreateEntity.class, UpdateEntity.class }) @@ -27,49 +40,71 @@ groups = { CreateEntity.class, UpdateEntity.class }) @ValidI18NName(message = "VALIDATION.VDS_GROUP.NAME.INVALID", groups = { CreateEntity.class, UpdateEntity.class }) + @Column(name = "name") private String name; @Size(max = BusinessEntitiesDefinitions.GENERAL_MAX_SIZE) + @Column(name = "description") private String description; + @Transient private String comment; @Size(max = BusinessEntitiesDefinitions.CLUSTER_CPU_NAME_SIZE) + @Column(name = "cpu_name") private String cpu_name; + @Column(name = "storage_pool_id") + @Type(type = "org.ovirt.engine.core.dao.GuidMapper") private Guid storagePoolId; @Size(max = BusinessEntitiesDefinitions.DATACENTER_NAME_SIZE) + @Transient private String storagePoolName; + @Column(name = "max_vds_memory_over_commit") private int max_vds_memory_over_commit; + @Column(name = "enable_balloon") private boolean enableBallooning; + @Column(name = "count_threads_as_cores") private boolean countThreadsAsCores; @Size(max = BusinessEntitiesDefinitions.GENERAL_VERSION_SIZE) + @Column(name = "compatibility_version") private String compatibility_version; + @Transient private Version compatVersion; + @Column(name = "transparent_hugepages") private boolean transparentHugepages; @NotNull(message = "VALIDATION.VDS_GROUP.MigrateOnError.NOT_NULL") + @Column(name = "migrate_on_error") private MigrateOnErrorOptions migrateOnError; + @Column(name = "virt_service") private boolean virtService; + @Column(name = "gluster_service") private boolean glusterService; + @Column(name = "tunnel_migration") private boolean tunnelMigration; + @Column(name = "emulated_machine") private String emulatedMachine; + @Column(name = "trusted_service") private boolean trustedService; + @Column(name = "cluster_policy_id") + @Type(type = "org.ovirt.engine.core.dao.GuidMapper") private Guid clusterPolicyId; + @Transient private String clusterPolicyName; @ValidUri(message = "VALIDATION.VDS_GROUP.SPICE_PROXY.HOSTNAME_OR_IP", @@ -77,10 +112,16 @@ @Size(max = BusinessEntitiesDefinitions.SPICE_PROXY_ADDR_SIZE) private String spiceProxy; + @Transient private Map<String, String> clusterPolicyProperties; + + @Column(name = "detect_emulated_machine") private boolean detectEmulatedMachine; + @Transient private ArchitectureType architecture; + + @Transient private OptimizationType optimizationType; public VDSGroup() { diff --git a/backend/manager/modules/dal/pom.xml b/backend/manager/modules/dal/pom.xml index 33e08c5..0ac279d 100644 --- a/backend/manager/modules/dal/pom.xml +++ b/backend/manager/modules/dal/pom.xml @@ -84,6 +84,11 @@ <groupId>org.infinispan</groupId> <artifactId>infinispan-core</artifactId> </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-entitymanager</artifactId> + <version>4.3.0.Final</version> + </dependency> </dependencies> <build> <filters> diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/GuidMapper.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/GuidMapper.java new file mode 100644 index 0000000..fd9bbb5 --- /dev/null +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/GuidMapper.java @@ -0,0 +1,99 @@ +package org.ovirt.engine.core.dao; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.UUID; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.usertype.UserType; +import org.ovirt.engine.core.compat.Guid; + +public class GuidMapper implements UserType { + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + @Override + public Object deepCopy(Object val) throws HibernateException { + if (val == null) + return null; + + if (val instanceof byte[]) { + return new Guid((byte[]) val, true); + } + + if (val instanceof UUID) + return new Guid((UUID) val); + + if (val instanceof Guid) + return new Guid(((Guid) val).getUuid()); + + throw new UnsupportedOperationException("Can't convert " + val.getClass() + " to GUID"); + } + + @Override + public Serializable disassemble(Object val) throws HibernateException { + if (val instanceof byte[]) { + return new Guid((byte[]) val, true); + } + + if (val instanceof UUID) + return new Guid((UUID) val); + + throw new UnsupportedOperationException("Can't convert " + val.getClass() + " to GUID"); + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + return x.equals(y); + } + + @Override + public int hashCode(Object value) throws HibernateException { + return value.hashCode(); + } + + @Override + public boolean isMutable() { + return true; + } + + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner) + throws HibernateException, SQLException { + + Object value = rs.getObject(names[0]); + if (value == null) + return null; + + return new Guid((UUID) value); + } + + @Override + public void nullSafeSet(PreparedStatement stmt, Object value, int index, SessionImplementor si) + throws HibernateException, SQLException { + stmt.setObject(index, ((Guid) value).getUuid()); + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + @Override + public Class returnedClass() { + return Guid.class; + } + + @Override + public int[] sqlTypes() { + return new int[] { Types.BLOB }; + } + +} diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/HibernateFacade.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/HibernateFacade.java new file mode 100644 index 0000000..8ff84a4 --- /dev/null +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/HibernateFacade.java @@ -0,0 +1,29 @@ +package org.ovirt.engine.core.dao; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public abstract class HibernateFacade extends BaseDAODbFacade { + private static volatile EntityManagerFactory emf; + + protected EntityManager getEntityManager() { + if (emf == null) { + synchronized (HibernateFacade.class) { + if (emf == null) { + emf = Persistence.createEntityManagerFactory("ovirt"); + } + } + } + return emf.createEntityManager(); + } + + public static EntityManagerFactory getEntityManagerFactory() { + return emf; + } + + public static void setEntityManagerFactory(EntityManagerFactory emf) { + HibernateFacade.emf = emf; + } + +} diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsGroupDAODbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsGroupDAODbFacadeImpl.java index ce4a1bc..1cee643 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsGroupDAODbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsGroupDAODbFacadeImpl.java @@ -5,6 +5,11 @@ import java.util.LinkedHashMap; import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + import org.ovirt.engine.core.common.businessentities.ActionGroup; import org.ovirt.engine.core.common.businessentities.ArchitectureType; import org.ovirt.engine.core.common.businessentities.MigrateOnErrorOptions; @@ -22,18 +27,23 @@ * found in {@link org.ovirt.engine.core.dal.dbbroker.DbFacade}. * */ -public class VdsGroupDAODbFacadeImpl extends BaseDAODbFacade implements VdsGroupDAO { +public class VdsGroupDAODbFacadeImpl extends HibernateFacade implements VdsGroupDAO { @Override public VDSGroup get(Guid id) { - return get(id, null, false); + return getEntityManager().find(VDSGroup.class, id); } @Override public VDSGroup get(Guid id, Guid userID, boolean isFiltered) { - MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() - .addValue("vds_group_id", id).addValue("user_id", userID).addValue("is_filtered", isFiltered); + EntityManager em = getEntityManager(); + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery<VDSGroup> query = cb.createQuery(VDSGroup.class); + Root<VDSGroup> group = query.from(VDSGroup.class); + query.where(cb.and(cb.equal(group.get("id"), id), + cb.and(cb.equal(group.get("user_id"), userID), + cb.equal(group.get("is_filtered"), isFiltered)))); - return getCallsHandler().executeRead("GetVdsGroupByVdsGroupId", VdsGroupRowMapper.instance, parameterSource); + return em.createQuery(query).getSingleResult(); } @Override diff --git a/backend/manager/modules/dal/src/main/resources/META-INF/persistence.xml b/backend/manager/modules/dal/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..e48edd9 --- /dev/null +++ b/backend/manager/modules/dal/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,12 @@ +<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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" + version="2.0"> + <persistence-unit name="ovirt"> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <class>org.ovirt.engine.core.common.businessentities.VDSGroup</class> + <properties> + <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> + </properties> + </persistence-unit> +</persistence> diff --git a/backend/manager/modules/dal/src/test/java/META-INF/persistence.xml b/backend/manager/modules/dal/src/test/java/META-INF/persistence.xml new file mode 100644 index 0000000..366135a --- /dev/null +++ b/backend/manager/modules/dal/src/test/java/META-INF/persistence.xml @@ -0,0 +1,12 @@ +<persistence> + <persistence-unit name="ovirt"> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <properties> + <property name="javax.persistence.jdbc.driver" value="${engine.db.driver}" /> + <property name="javax.persistence.jdbc.user" value="${engine.db.username}" /> + <property name="javax.persistence.jdbc.password" value="${engine.db.password}" /> + <property name="javax.persistence.jdbc.url" value="${engine.db.url}" /> + <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> + </properties> + </persistence-unit> +</persistence> diff --git a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VdsGroupDAOTest.java b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VdsGroupDAOTest.java index fab5f1b..ededb8c 100644 --- a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VdsGroupDAOTest.java +++ b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VdsGroupDAOTest.java @@ -7,9 +7,16 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; import org.junit.Test; import org.ovirt.engine.core.common.businessentities.ArchitectureType; @@ -37,6 +44,26 @@ public void setUp() throws Exception { super.setUp(); + Properties properties = new Properties(); + + InputStream is = null; + is = BaseDAOTestCase.class.getResourceAsStream("/test-database.properties"); + try { + properties.load(is); + } catch (Exception e) { + e.printStackTrace(); + } + + Map props = new HashMap(); + props.put("javax.persistence.jdbc.driver", properties.getProperty("database.driver")); + props.put("javax.persistence.jdbc.user", properties.getProperty("database.username")); + props.put("javax.persistence.jdbc.password", properties.getProperty("database.password")); + props.put("javax.persistence.jdbc.url", properties.getProperty("database.url")); + + EntityManagerFactory emf = Persistence.createEntityManagerFactory("ovirt", props); + + HibernateFacade.setEntityManagerFactory(emf); + VdsDAO vdsDAO = dbFacade.getVdsDao(); existingVds = vdsDAO.get(FixturesTool.VDS_RHEL6_NFS_SPM); @@ -63,7 +90,6 @@ newGroup.setDetectEmulatedMachine(true); newGroup.setEmulatedMachine("rhel6.4.0"); newGroup.setArchitecture(ArchitectureType.x86_64); - } /** -- To view, visit http://gerrit.ovirt.org/22806 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3cd0bbf9f0913955cb3e1facfa9a4bdc1f1ab24d Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Liran Zelkha <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
