Search code examples
javaspring-bootbyte-buddy

Byte Buddy Runtime generation for spring boot JPA repository classes


I am using Byte Buddy to generate JPA entities and JPA repository. I am able to generate the JPA entities but not able to proceed in generating corresponding JPA repositories. Following is the code which represent Person entity,

import javax.persistence.*;
@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    protected Person(){}

    @Override
    public String toString() {
        return String.format("Person[id=%d]",id,name);
    }
}

I am able to generate the above using Bute Buddy as follows,

Class<?> type = new ByteBuddy()
    .subclass(Object.class)
    .name("Person")
    .defineField("id", Integer.class, Visibility.PRIVATE)
    .defineMethod("getId", Integer.class, Visibility.PUBLIC)
    .intercept(FieldAccessor.ofBeanProperty())
    .defineMethod("setId", void.class, Visibility.PUBLIC).withParameter(Integer.class)
    .intercept(FieldAccessor.ofBeanProperty())
    .make()
    .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
    .getLoaded();

Now I would like to generate corresponding Spring boot Jpa reporitories as below,

import com.model.Person;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PersonRepository extends JpaRepository <Person, Long> {

}

How to create this interface with Generic attribute. Also will this work (using dynamic code generation) to persist Person object?


Solution

  • You can use the TypeDescription.Generic.Builder::parameterizedType to create a generic type:

    TypeDescription.Generic genericType = TypeDescription.Generic.Builder
       .parameterizedType(JpaRepository.class, type, Long.class)
       .build();
    

    You can then supply this generic type to ByteBuddy::makeInterface:

    DynamicType dt = new ByteBuddy()
      .makeInterface(genericType)
      .name("com.model.Person")
      .make();
    

    A Byte Buddy generated class cannot be distinguished from one generated by javac, therefore this should work just as expected.