Skip to content

Commit

Permalink
DATAJPA-28 - Added support for XML based metadata.
Browse files Browse the repository at this point in the history
Added IsNewAware and IdAware implementation that uses JPA 2.0 meta model API to find the id field. Using that instead of JpaAnnotationEntityInformation to be able to use XML based entity mapping as well. Changed mapping of Role sample domain class to XML and created integration test to verify XML metadata is considered as well.
  • Loading branch information
odrotbohm committed Feb 23, 2011
1 parent 14a69ea commit e48ec42
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 315 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2008-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.repository.support;

import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;

import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.SingularAttribute;

import org.springframework.data.repository.support.IdAware;
import org.springframework.data.repository.support.IsNewAware;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;


/**
* Implementation of {@link IsNewAware} and {@link IdAware} that uses JPA
* {@link Metamodel} to find the domain class' id field.
*
* @author Oliver Gierke
*/
public class JpaMetamodelEntityInformation implements IsNewAware, IdAware {

private final Member member;


/**
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain
* class and {@link Metamodel}.
*
* @param domainClass
* @param metamodel
*/
public JpaMetamodelEntityInformation(Class<?> domainClass,
Metamodel metamodel) {

Assert.notNull(domainClass);
Assert.notNull(metamodel);

EntityType<?> type = metamodel.entity(domainClass);

SingularAttribute<?, ?> idAttribute =
type.getId(type.getIdType().getJavaType());
this.member = idAttribute.getJavaMember();
}


/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
* )
*/
public Object getId(Object entity) {

return getMemberValue(member, entity);
}


/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.IsNewAware#isNew(java.lang
* .Object)
*/
public boolean isNew(Object entity) {

return getId(entity) == null;
}


/**
* Returns the value of the given {@link Member} of the given {@link Object}
* .
*
* @param member
* @param source
* @return
*/
private static Object getMemberValue(Member member, Object source) {

if (member instanceof Field) {
Field field = (Field) member;
ReflectionUtils.makeAccessible(field);
return ReflectionUtils.getField(field, source);
} else if (member instanceof Method) {
Method method = (Method) member;
ReflectionUtils.makeAccessible(method);
return ReflectionUtils.invokeMethod(method, source);
}

throw new IllegalArgumentException(
"Given member is neither Field nor Method!");
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
Expand All @@ -32,9 +33,14 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Persistable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.support.IsNewAware;
import org.springframework.data.repository.support.PersistableEntityInformation;
import org.springframework.data.repository.support.RepositorySupport;
import org.springframework.util.Assert;


Expand All @@ -49,7 +55,7 @@
*/
@org.springframework.stereotype.Repository
public class SimpleJpaRepository<T, ID extends Serializable> extends
JpaRepositorySupport<T, ID> {
RepositorySupport<T, ID> implements JpaRepository<T, ID> {

private final EntityManager em;
private final PersistenceProvider provider;
Expand Down Expand Up @@ -355,7 +361,45 @@ public void flush() {
}


/*
* (non-Javadoc)
*
* @see
* org.springframework.data.jpa.repository.support.JpaRepositorySupport#
* createIsNewStrategy(java.lang.Class)
*/
@Override
protected final IsNewAware createIsNewStrategy(Class<?> domainClass) {

return createIsNewStrategy(domainClass, em);
}


/**
* Creates a new {@link IsNewAware} instance for the given domain class and
* {@link EntityManager}.
*
* @param domainClass
* @param em
* @return
*/
protected IsNewAware createIsNewStrategy(Class<?> domainClass,
EntityManager em) {

if (Persistable.class.isAssignableFrom(domainClass)) {
return new PersistableEntityInformation();
} else {
EntityManagerFactory emf = em.getEntityManagerFactory();
return new JpaMetamodelEntityInformation(domainClass,
emf.getMetamodel());
}
}


/**
* Reads the given {@link TypedQuery} into a {@link Page} applying the given
* {@link Pageable} and {@link Specification}.
*
* @param query
* @param spec
* @param pageable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,17 @@
*/
package org.springframework.data.jpa.domain.sample;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;


/**
* Example implementation of the very basic {@code Persistable} interface. The
* id type is matching the typisation of the interface.
* {@code Persitsable#isNew()} is implemented regarding the id as flag.
* Sample domain class representing roles. Mapped with XML.
*
* @author Oliver Gierke
*/
@Entity
public class Role {

private static final long serialVersionUID = -8832631113344035104L;

private static final String PREFIX = "ROLE_";

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String name;


Expand Down
Loading

0 comments on commit e48ec42

Please sign in to comment.