Skip to content

Commit

Permalink
Spring data jpa with MappedSuperclass, fixes quarkusio#5261
Browse files Browse the repository at this point in the history
  • Loading branch information
Erin Schnabel authored and ia3andy committed Nov 19, 2019
1 parent 203f1fa commit 7212d05
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.stream.Stream;

import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import org.jboss.jandex.DotName;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -63,6 +64,7 @@ public final class DotNames {
.createSimple(Modifying.class.getName());

public static final DotName JPA_ID = DotName.createSimple(Id.class.getName());
public static final DotName JPA_MAPPED_SUPERCLASS = DotName.createSimple(MappedSuperclass.class.getName());
public static final DotName VOID = DotName.createSimple(void.class.getName());
public static final DotName LONG = DotName.createSimple(Long.class.getName());
public static final DotName PRIMITIVE_LONG = DotName.createSimple(long.class.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;

import io.quarkus.panache.common.Sort;

Expand Down Expand Up @@ -57,10 +60,12 @@ public class MethodNameParser {

private final ClassInfo entityClass;
private final IndexView indexView;
private final List<ClassInfo> mappedSuperClassInfos;

public MethodNameParser(ClassInfo entityClass, IndexView indexView) {
this.entityClass = entityClass;
this.indexView = indexView;
this.mappedSuperClassInfos = getMappedSuperClassInfos(indexView, entityClass);
}

public enum QueryType {
Expand Down Expand Up @@ -185,7 +190,7 @@ public Result parse(MethodInfo methodInfo) {
} else {
fieldName = lowerFirstLetter(part.replaceAll(operation, ""));
}
FieldInfo fieldInfo = entityClass.field(fieldName);
FieldInfo fieldInfo = getField(fieldName);
if (fieldInfo == null) {
String parsingExceptionMethod = "Entity " + entityClass + " does not contain a field named: " + part + ". " +
"Offending method is " + methodName;
Expand Down Expand Up @@ -213,7 +218,7 @@ public Result parse(MethodInfo methodInfo) {

String simpleFieldName = fieldName.substring(0, fieldEndIndex);
String associatedEntityFieldName = lowerFirstLetter(fieldName.substring(associatedEntityFieldStartIndex));
fieldInfo = entityClass.field(simpleFieldName);
fieldInfo = getField(simpleFieldName);
if ((fieldInfo == null) || !(fieldInfo.type() instanceof ClassType)) {
throw new UnableToParseMethodException(parsingExceptionMethod);
}
Expand Down Expand Up @@ -428,7 +433,52 @@ private String getEntityName() {
}

private boolean entityContainsField(String fieldName) {
return entityClass.field(fieldName) != null;
if (entityClass.field(fieldName) != null) {
return true;
}

for (ClassInfo superClass : mappedSuperClassInfos) {
FieldInfo fieldInfo = superClass.field(fieldName);
if (fieldInfo != null) {
return true;
}
}
return false;
}

private FieldInfo getField(String fieldName) {
FieldInfo fieldInfo = entityClass.field(fieldName);
if (fieldInfo == null) {
for (ClassInfo superClass : mappedSuperClassInfos) {
fieldInfo = superClass.field(fieldName);
if (fieldInfo != null) {
break;
}
}
}
return fieldInfo;
}

private List<ClassInfo> getMappedSuperClassInfos(IndexView indexView, ClassInfo entityClass) {
List<ClassInfo> mappedSuperClassInfos = new ArrayList<>(3);
Type superClassType = entityClass.superClassType();
while (superClassType != null && !superClassType.name().equals(DotNames.OBJECT)) {
ClassInfo superClass = indexView.getClassByName(entityClass.superName());
if (superClass.classAnnotation(DotNames.JPA_MAPPED_SUPERCLASS) != null) {
mappedSuperClassInfos.add(superClass);
}

if (superClassType.kind() == Kind.CLASS) {
superClassType = indexView.getClassByName(superClassType.name()).superClassType();
} else if (superClassType.kind() == Kind.PARAMETERIZED_TYPE) {
ParameterizedType parameterizedType = superClassType.asParameterizedType();
superClassType = parameterizedType.owner();
}
}
if (mappedSuperClassInfos.size() > 0) {
return mappedSuperClassInfos;
}
return Collections.emptyList();
}

public static class Result {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@
import javax.persistence.Id;

@Entity
public class Book {
public class Book extends NamedEntity {

private Integer bid;

private String name;
private Integer publicationYear;

public Book() {
}

public Book(Integer bid, String name, Integer publicationYear) {
super(name);
this.bid = bid;
this.name = name;
this.publicationYear = publicationYear;
}

Expand All @@ -29,14 +28,6 @@ public void setBid(Integer bid) {
this.bid = bid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getPublicationYear() {
return publicationYear;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public interface BookRepository extends Repository<Book, Integer> {

List<Book> findAll();

List<Book> findByName(String name);

boolean existsById(Integer id);

boolean existsBookByPublicationYearBetween(Integer start, Integer end);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ public boolean existsById(@PathParam("bid") Integer bid) {
public boolean existsByPublicationYearBetween(@PathParam("start") Integer start, @PathParam("end") Integer end) {
return bookRepository.existsBookByPublicationYearBetween(start, end);
}

@GET
@Path("/name/{name}")
@Produces("application/json")
public List<Book> byName(@PathParam("name") String name) {
return bookRepository.findByName(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,27 @@
import javax.persistence.SequenceGenerator;

@Entity
public class Country {
public class Country extends NamedEntity {

@Id
@SequenceGenerator(name = "countrySeqGen", sequenceName = "countrySeq", initialValue = 4, allocationSize = 1)
@GeneratedValue(generator = "countrySeqGen")
public Long id;

private String name;

private String iso3;

public Country() {
}

public Country(String name, String iso3) {
this.name = name;
super(name);
this.iso3 = iso3;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getIso3() {
return iso3;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.quarkus.it.spring.data.jpa;

import javax.persistence.MappedSuperclass;

@MappedSuperclass
public class NamedEntity {

private String name;

public NamedEntity() {
}

public NamedEntity(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,18 @@ void testNew() {
.body(containsString("Upheaval"))
.body(containsString("Sapiens"));
}

@Test
void testByName() {
when().get("/book/name/Sapiens").then()
.statusCode(200)
.body(containsString("Sapiens"));
}

@Test
void testByNameNotFound() {
when().get("/book/name/DoesNotExist").then()
.statusCode(200)
.body("size()", is(0));
}
}

0 comments on commit 7212d05

Please sign in to comment.