add to src/test/resources/application.properties
or src/main/resources/application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=INFO
- JPA translates entity state transitions to database DML statements. Because it’s common to operate on entity graphs, JPA allows us to propagate entity state changes from Parents to Child entities. This behavior is configured through the CascadeType mappings.
@OneToMany(cascade = CascadeType.ALL, mappedBy = "<the other class property>")
@ManyToOne
@JoinColumn(name = "<foreign key in dieser Tabelle>", nullable = false)
//@JoinColumn 'name' ist der foreign key in dieser Tabelle, der auf "id" in anderen Tabelle zeigt
private TheOtherClass otherObj;
- Insert a new register to the database
- Attach the object to the entity manager.
- Find an attached object with the same id and update it.
- If exists update and return the already attached object.
- If doesn't exist insert the new register to the database.
- It could be more efficient for inserting a new register to a database than merge().
- It doesn't duplicates the original object.
- It makes sure that you are inserting and not updating by mistake.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
//GenerationType.AUTO besser weil GenerationType.IDENTITY=bad optimization in hibernate
//
@Column(name = "id")
private Long id;
Im grunde reicht es das Interface JpaRepository
zu extenden:
public interface MeineEntityKlasseRepository extends JpaRepository<MeineEntityKlasse,Long> {}
wobei der primary key hier ein im Beispiel ein Long
ist.
@RepositoryRestResource(collectionResourceRel = "jsonName", path = "api-url-pfad-name")
public interface MeineEntityKlasseRepository extends JpaRepository<MeineEntityKlasse,Long> {}
- wobei
path = "<api-url-pfad name>"
der aufrufpfad für den rest-call ist , also z.B./api-url-pfad-name
- Dagegen ist
jsonName
der name den das Feld im zurückgegebenen JSON Dokument hat. - meist gild:
collectionResourceRel.equals(path)
muss aber nicht so sein.
- das Interface wird einfach mit einer Method-Signature ergänzt:
public Page<MyActualClass> findByMySelectionID (@RequestParameter("id") Long id, Pageable pageble);
- der alles andere ist Springboot - Magic und führt zu folgendem SQL:
SELECT * FROM myclass where myselection_id=?
http://localhost:8080/api/myactualclass/search
sollte dann diefindBymyselectionId
anzeigen undhttp://localhost:8080/api/myactualclass/search/findByMyselectionId?id=1
müsste dann die gefilterten Ergebnisse liefern- allgemein kann man die
findBy
-methoden - Varianten, die man im INterface definieren kann hier finden:
Beispiele:
@CrossOrigin("http://localhost:4200")
public interface ProductRepository extends JpaRepository<Product,Long> {
public Page<Product> findByCategoryId(@RequestParam("id") Long id, Pageable pageable);
public Page<Product> findByNameContainingOrDescriptionContaining(@RequestParam("name") String name,
@RequestParam("description") String description ,
Pageable pageable);
}
Änderung für "MyClass", read only:
@Configuration
public class RestConfig implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration restConfig) {
HttpMethod[] theUnsupportedActions = {HttpMethod.PUT,HttpMethod.POST,HttpMethod.DELETE};
restConfig.getExposureConfiguration()
.forDomainType(<MyClass>.class)
.withItemExposure((metadata,httpMethods)-> httpMethods.disable(theUnsupportedActions))
.withCollectionExposure((metadata,httpMethods)-> httpMethods.disable(theUnsupportedActions));
}
}
GGf. braucht man noch ein EntityManager Instanz für die Configänderung, dann ergänze: eine Constructor der den EnitiyManager per @Autowired injektet.
....
private EntityManager entityManager;
@Autowired
public RestConfig(EntityManager theEntityManager){
this.entityManager= theEntityManager;
}
...
z.B. um vom EntityManager alle Typen, die er verwaltet zu lesen:
...
for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {
logger.debug("Java Type:" + entity.getJavaType().toString());
restConfig.exposeIdsFor(entity.getJavaType())
}
...
das kann man verwenden um die dann einzeln zu Konfigurieren, hier z.B. um die Id in der Json Antwort mit einzuschließen (was eben defaultmäßig nicht der Fall ist):
config.exposeIdsFor(User.class)
wenn User.class eine von den Entitys des EntityMangers ist;
JpaRepository<my-stuff,Long> hat beim Zugriff über http://whatever/api/my-stuff
schon eingebaute Argumente,
- z.b.
?size=<number>
(default ist 20) - also
http://whatever/api/my-stuf?size=100
liefert dann 100 Ergebnisse.
ist per default schon dabei ! siehe das"page"
Json - Element am Ende eines Reply-Content !
http://localhost:8080/api/products{?page,size,sort}
z.B. http://localhost:8080/api/products?page=2&size=2
...werden wieder durch Annoations definiert :
@Entity
, mandatory@Table
(mit argumentname=<name der Tabelle in der DB>
)- Lobok:
@Data
oder@Getter
@Setter
@ID
für den primary key mandatory, dazu optional@GeneratedValue
(meistAuto
)@Column
optional, wenn man die DB-Spalte anders nennen will
@CrossOrigin("http://localhost:4200")
dem inferface
hinzufügen , welches JpaRepository<>
extended