mirror of
https://github.com/dalbodeule/snap-admin.git
synced 2025-06-09 05:48:20 +00:00
WIP
This commit is contained in:
parent
9e2a5fa80b
commit
49112fe60b
@ -110,8 +110,7 @@ This annotation can be placed on binary fields to declare they are storing an im
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
0.0.3 - @DisplayImage
|
0.0.3 - @DisplayImage; Selenium tests; Fixed/greatly improved edit page;
|
||||||
|
|
||||||
|
|
||||||
0.0.2 - Faceted search with `@Filterable` annotation
|
0.0.2 - Faceted search with `@Filterable` annotation
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class the get the ApplicationContext
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ApplicationContextUtils implements ApplicationContextAware {
|
public class ApplicationContextUtils implements ApplicationContextAware {
|
||||||
|
|
||||||
|
@ -35,6 +35,15 @@ import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
|
|||||||
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
||||||
import tech.ailef.dbadmin.misc.Utils;
|
import tech.ailef.dbadmin.misc.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main DbAdmin class responsible for the initialization phase. This class scans
|
||||||
|
* the user provided package containing the `@Entity` definitions and tries to map each
|
||||||
|
* entity to a DbObjectSchema instance.
|
||||||
|
*
|
||||||
|
* This process involves determining the correct type for each class field and its
|
||||||
|
* configuration at the database level. An exception will be thrown if it's not possible
|
||||||
|
* to determine the field type.
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class DbAdmin {
|
public class DbAdmin {
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
@ -57,10 +66,6 @@ public class DbAdmin {
|
|||||||
this.modelsPackage = applicationClass.getModelsPackage();
|
this.modelsPackage = applicationClass.getModelsPackage();
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||||
provider.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
|
provider.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
|
||||||
|
|
||||||
@ -70,6 +75,45 @@ public class DbAdmin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the loaded schemas (i.e. entity classes)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<DbObjectSchema> getSchemas() {
|
||||||
|
return Collections.unmodifiableList(schemas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a schema by its full class name
|
||||||
|
* @param className qualified class name
|
||||||
|
* @return
|
||||||
|
* @throws DbAdminException if corresponding schema not found
|
||||||
|
*/
|
||||||
|
public DbObjectSchema findSchemaByClassName(String className) {
|
||||||
|
return schemas.stream().filter(s -> s.getClassName().equals(className)).findFirst().orElseThrow(() -> {
|
||||||
|
return new DbAdminException("Schema " + className + " not found.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a schema by its class
|
||||||
|
* @param klass
|
||||||
|
* @return
|
||||||
|
* @throws DbAdminException if corresponding schema not found
|
||||||
|
*/
|
||||||
|
public DbObjectSchema findSchemaByClass(Class<?> klass) {
|
||||||
|
return findSchemaByClassName(klass.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method processes a BeanDefinition into a DbObjectSchema object,
|
||||||
|
* where all fields have been correctly mapped to DbField objects.
|
||||||
|
*
|
||||||
|
* If any field is not mappable, the method will throw an exception.
|
||||||
|
* @param bd
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private DbObjectSchema processBeanDefinition(BeanDefinition bd) {
|
private DbObjectSchema processBeanDefinition(BeanDefinition bd) {
|
||||||
String fullClassName = bd.getBeanClassName();
|
String fullClassName = bd.getBeanClassName();
|
||||||
|
|
||||||
@ -88,9 +132,7 @@ public class DbAdmin {
|
|||||||
System.out.println(" - Mapping field " + f);
|
System.out.println(" - Mapping field " + f);
|
||||||
DbField field = mapField(f, schema);
|
DbField field = mapField(f, schema);
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
// continue;
|
throw new DbAdminException("Impossible to map field: " + f);
|
||||||
// TODO: CHECK THIS EXCEPTION
|
|
||||||
throw new DbAdminException("IMPOSSIBLE TO MAP FIELD: " + f);
|
|
||||||
}
|
}
|
||||||
field.setSchema(schema);
|
field.setSchema(schema);
|
||||||
|
|
||||||
@ -123,6 +165,11 @@ public class DbAdmin {
|
|||||||
return fieldName;
|
return fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a field is nullable from the `@Column` annotation
|
||||||
|
* @param f
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private boolean determineNullable(Field f) {
|
private boolean determineNullable(Field f) {
|
||||||
Column[] columnAnnotations = f.getAnnotationsByType(Column.class);
|
Column[] columnAnnotations = f.getAnnotationsByType(Column.class);
|
||||||
|
|
||||||
@ -135,6 +182,15 @@ public class DbAdmin {
|
|||||||
return nullable;
|
return nullable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a DbField object from a primitive Java field. This process involves
|
||||||
|
* determining the correct field name on the database, its type and additional
|
||||||
|
* attributes (e.g. nullable).
|
||||||
|
* This method returns null if a field cannot be mapped to a supported type.
|
||||||
|
* @param f primitive Java field to construct a DbField from
|
||||||
|
* @param schema the schema this field belongs to
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private DbField mapField(Field f, DbObjectSchema schema) {
|
private DbField mapField(Field f, DbObjectSchema schema) {
|
||||||
OneToMany oneToMany = f.getAnnotation(OneToMany.class);
|
OneToMany oneToMany = f.getAnnotation(OneToMany.class);
|
||||||
ManyToMany manyToMany = f.getAnnotation(ManyToMany.class);
|
ManyToMany manyToMany = f.getAnnotation(ManyToMany.class);
|
||||||
@ -208,7 +264,7 @@ public class DbAdmin {
|
|||||||
* Returns the type of a foreign key field, by looking at the type
|
* Returns the type of a foreign key field, by looking at the type
|
||||||
* of the primary key (defined as `@Id`) in the referenced table.
|
* of the primary key (defined as `@Id`) in the referenced table.
|
||||||
*
|
*
|
||||||
* @param f
|
* @param entityClass
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private DbFieldType mapForeignKeyType(Class<?> entityClass) {
|
private DbFieldType mapForeignKeyType(Class<?> entityClass) {
|
||||||
@ -231,26 +287,4 @@ public class DbAdmin {
|
|||||||
throw new DbAdminException(e);
|
throw new DbAdminException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBasePackage() {
|
|
||||||
return modelsPackage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DbObjectSchema> getSchemas() {
|
|
||||||
return Collections.unmodifiableList(schemas);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbObjectSchema findSchemaByClassName(String className) {
|
|
||||||
return schemas.stream().filter(s -> s.getClassName().equals(className)).findFirst().orElseThrow(() -> {
|
|
||||||
return new DbAdminException("Schema " + className + " not found.");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbObjectSchema findSchemaByClass(Class<?> klass) {
|
|
||||||
return findSchemaByClassName(klass.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityManager getEntityManager() {
|
|
||||||
return entityManager;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,12 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation marks a method as a "virtual" whose value is computed by
|
||||||
|
* using the method itself rather than retrieving it like a physical column
|
||||||
|
* from the database.
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface ComputedColumn {
|
public @interface ComputedColumn {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package tech.ailef.dbadmin.annotations;
|
package tech.ailef.dbadmin.annotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that includes all the configuration methods that
|
||||||
|
* the user has to implement in order to integrate DbAdmin.
|
||||||
|
*
|
||||||
|
*/
|
||||||
public interface DbAdminAppConfiguration {
|
public interface DbAdminAppConfiguration {
|
||||||
public String getModelsPackage();
|
public String getModelsPackage();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the class that holds the DbAdmin configuration.
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface DbAdminConfiguration {
|
public @interface DbAdminConfiguration {
|
||||||
|
@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a format string for a field, which will be automatically applied
|
||||||
|
* when displaying its value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface DisplayFormat {
|
public @interface DisplayFormat {
|
||||||
|
@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a binary field as containing an image, which in turn enables
|
||||||
|
* its display in the interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface DisplayImage {
|
public @interface DisplayImage {
|
||||||
|
@ -5,6 +5,12 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a method as returning a name that has to be used to display
|
||||||
|
* this item, in addition to its primary key. Use to give users more
|
||||||
|
* readable item names.
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface DisplayName {
|
public @interface DisplayName {
|
||||||
|
@ -5,6 +5,14 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a field as filterable and places it in the faceted search bar.
|
||||||
|
* (This bar only appears in the interface if one or more fields are filterable
|
||||||
|
* in the current schema.)
|
||||||
|
* Can only be placed on fields that correspond to physical columns on the
|
||||||
|
* table (e.g. no `@ManyToMany`/`@OneToMany`) and that are not binary (`byte[]`).
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface Filterable {
|
public @interface Filterable {
|
||||||
|
@ -11,6 +11,7 @@ import java.util.stream.Collectors;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.jdbc.UncategorizedSQLException;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
@ -36,29 +37,11 @@ import tech.ailef.dbadmin.dto.QueryFilter;
|
|||||||
import tech.ailef.dbadmin.exceptions.InvalidPageException;
|
import tech.ailef.dbadmin.exceptions.InvalidPageException;
|
||||||
import tech.ailef.dbadmin.misc.Utils;
|
import tech.ailef.dbadmin.misc.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main DbAdmin controller that register most of the routes of the web interface.
|
||||||
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/dbadmin")
|
@RequestMapping("/dbadmin")
|
||||||
/**
|
|
||||||
* FOR 0.0.3:
|
|
||||||
* @DisplayImage DONE TODO: write docs in README
|
|
||||||
* Fixed/improved edit page for binary fields (files) DONE
|
|
||||||
*
|
|
||||||
* TODO
|
|
||||||
* - double data source for internal database and settings
|
|
||||||
* - role based authorization (PRO)
|
|
||||||
* - Pagination in one to many results?
|
|
||||||
* - AI console (PRO)
|
|
||||||
* - Action logs
|
|
||||||
* - Boolean icons
|
|
||||||
* - Boolean in create/edit is checkbox
|
|
||||||
* - Documentation
|
|
||||||
* - SQL console (PRO)
|
|
||||||
* - JPA Validation (PRO)
|
|
||||||
* - Logging
|
|
||||||
* - Selenium tests
|
|
||||||
* - Logs in web ui
|
|
||||||
* - Tests: AutocompleteController, REST API, create/edit
|
|
||||||
*/
|
|
||||||
public class DefaultDbAdminController {
|
public class DefaultDbAdminController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DbAdminRepository repository;
|
private DbAdminRepository repository;
|
||||||
@ -66,6 +49,12 @@ public class DefaultDbAdminController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DbAdmin dbAdmin;
|
private DbAdmin dbAdmin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Home page with list of schemas
|
||||||
|
* @param model
|
||||||
|
* @param query
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public String index(Model model, @RequestParam(required = false) String query) {
|
public String index(Model model, @RequestParam(required = false) String query) {
|
||||||
List<DbObjectSchema> schemas = dbAdmin.getSchemas();
|
List<DbObjectSchema> schemas = dbAdmin.getSchemas();
|
||||||
@ -88,6 +77,24 @@ public class DefaultDbAdminController {
|
|||||||
return "home";
|
return "home";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists the items of a schema by applying a variety of filters:
|
||||||
|
* - query: fuzzy search
|
||||||
|
* - otherParams: filterable fields
|
||||||
|
* Includes pagination and sorting options.
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
* @param className
|
||||||
|
* @param page
|
||||||
|
* @param query
|
||||||
|
* @param pageSize
|
||||||
|
* @param sortKey
|
||||||
|
* @param sortOrder
|
||||||
|
* @param otherParams
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@GetMapping("/model/{className}")
|
@GetMapping("/model/{className}")
|
||||||
public String list(Model model, @PathVariable String className,
|
public String list(Model model, @PathVariable String className,
|
||||||
@RequestParam(required=false) Integer page, @RequestParam(required=false) String query,
|
@RequestParam(required=false) Integer page, @RequestParam(required=false) String query,
|
||||||
@ -160,6 +167,12 @@ public class DefaultDbAdminController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays information about the schema
|
||||||
|
* @param model
|
||||||
|
* @param className
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@GetMapping("/model/{className}/schema")
|
@GetMapping("/model/{className}/schema")
|
||||||
public String schema(Model model, @PathVariable String className) {
|
public String schema(Model model, @PathVariable String className) {
|
||||||
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
|
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
|
||||||
@ -170,6 +183,13 @@ public class DefaultDbAdminController {
|
|||||||
return "model/schema";
|
return "model/schema";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a single item
|
||||||
|
* @param model
|
||||||
|
* @param className
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@GetMapping("/model/{className}/show/{id}")
|
@GetMapping("/model/{className}/show/{id}")
|
||||||
public String show(Model model, @PathVariable String className, @PathVariable String id) {
|
public String show(Model model, @PathVariable String className, @PathVariable String id) {
|
||||||
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
|
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
|
||||||
@ -333,6 +353,10 @@ public class DefaultDbAdminController {
|
|||||||
attr.addFlashAttribute("errorTitle", "Unable to INSERT row");
|
attr.addFlashAttribute("errorTitle", "Unable to INSERT row");
|
||||||
attr.addFlashAttribute("error", e.getMessage());
|
attr.addFlashAttribute("error", e.getMessage());
|
||||||
attr.addFlashAttribute("params", params);
|
attr.addFlashAttribute("params", params);
|
||||||
|
} catch (UncategorizedSQLException e) {
|
||||||
|
attr.addFlashAttribute("errorTitle", "Unable to INSERT row");
|
||||||
|
attr.addFlashAttribute("error", e.getMessage());
|
||||||
|
attr.addFlashAttribute("params", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -352,6 +376,10 @@ public class DefaultDbAdminController {
|
|||||||
attr.addFlashAttribute("errorTitle", "Unable to UPDATE row (no changes applied)");
|
attr.addFlashAttribute("errorTitle", "Unable to UPDATE row (no changes applied)");
|
||||||
attr.addFlashAttribute("error", e.getMessage());
|
attr.addFlashAttribute("error", e.getMessage());
|
||||||
attr.addFlashAttribute("params", params);
|
attr.addFlashAttribute("params", params);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
attr.addFlashAttribute("errorTitle", "Unable to UPDATE row (no changes applied)");
|
||||||
|
attr.addFlashAttribute("error", e.getMessage());
|
||||||
|
attr.addFlashAttribute("params", params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,6 +24,9 @@ import tech.ailef.dbadmin.dbmapping.DbObject;
|
|||||||
import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
|
import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
|
||||||
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to serve file or images (`@DisplayImage`)
|
||||||
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/dbadmin/download")
|
@RequestMapping("/dbadmin/download")
|
||||||
public class DownloadController {
|
public class DownloadController {
|
||||||
|
@ -159,16 +159,13 @@ public class AdvancedJpaRepository extends SimpleJpaRepository {
|
|||||||
|
|
||||||
CriteriaUpdate update = cb.createCriteriaUpdate(schema.getJavaClass());
|
CriteriaUpdate update = cb.createCriteriaUpdate(schema.getJavaClass());
|
||||||
|
|
||||||
Root employee = update.from(schema.getJavaClass());
|
Root root = update.from(schema.getJavaClass());
|
||||||
|
|
||||||
for (DbField field : schema.getSortedFields()) {
|
for (DbField field : schema.getSortedFields()) {
|
||||||
if (field.isPrimaryKey()) continue;
|
if (field.isPrimaryKey()) continue;
|
||||||
|
|
||||||
boolean keepValue = params.getOrDefault("__keep_" + field.getJavaName(), "off").equals("on");
|
boolean keepValue = params.getOrDefault("__keep_" + field.getName(), "off").equals("on");
|
||||||
|
if (keepValue) continue;
|
||||||
if (keepValue) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String stringValue = params.get(field.getName());
|
String stringValue = params.get(field.getName());
|
||||||
Object value = null;
|
Object value = null;
|
||||||
@ -187,11 +184,14 @@ public class AdvancedJpaRepository extends SimpleJpaRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update.set(employee.get(field.getJavaName()), value);
|
if (field.getConnectedSchema() != null)
|
||||||
|
value = field.getConnectedSchema().getJpaRepository().findById(value).get();
|
||||||
|
|
||||||
|
update.set(root.get(field.getJavaName()), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
String pkName = schema.getPrimaryKey().getJavaName();
|
String pkName = schema.getPrimaryKey().getJavaName();
|
||||||
update.where(cb.equal(employee.get(pkName), params.get(schema.getPrimaryKey().getName())));
|
update.where(cb.equal(root.get(pkName), params.get(schema.getPrimaryKey().getName())));
|
||||||
|
|
||||||
Query query = entityManager.createQuery(update);
|
Query query = entityManager.createQuery(update);
|
||||||
return query.executeUpdate();
|
return query.executeUpdate();
|
||||||
|
@ -131,16 +131,7 @@ public class DbAdminRepository {
|
|||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public void update(DbObjectSchema schema, Map<String, String> params, Map<String, MultipartFile> files) {
|
public void update(DbObjectSchema schema, Map<String, String> params, Map<String, MultipartFile> files) {
|
||||||
// Object[] updateArray = schema.getUpdateArray(params, files);
|
|
||||||
//
|
|
||||||
// String updateFields =
|
|
||||||
// schema.getSortedFields().stream().map(f -> "`" + f.getName() + "` = ?").collect(Collectors.joining(", "));
|
|
||||||
//
|
|
||||||
// String query = "UPDATE `" + schema.getTableName() + "` SET " + updateFields + " WHERE `" + schema.getPrimaryKey().getName() + "` = ?";
|
|
||||||
// jdbcTemplate.update(query, updateArray);
|
|
||||||
|
|
||||||
schema.getJpaRepository().update(schema, params, files);
|
schema.getJpaRepository().update(schema, params, files);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -125,7 +125,9 @@ public class DbObject {
|
|||||||
|
|
||||||
if (displayNameMethod.isPresent()) {
|
if (displayNameMethod.isPresent()) {
|
||||||
try {
|
try {
|
||||||
return displayNameMethod.get().invoke(instance).toString();
|
Object displayName = displayNameMethod.get().invoke(instance);
|
||||||
|
if (displayName == null) return null;
|
||||||
|
else return displayName.toString();
|
||||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||||
throw new DbAdminException(e);
|
throw new DbAdminException(e);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
|
|
||||||
import jakarta.persistence.ManyToMany;
|
import jakarta.persistence.ManyToMany;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import tech.ailef.dbadmin.DbAdmin;
|
import tech.ailef.dbadmin.DbAdmin;
|
||||||
import tech.ailef.dbadmin.annotations.ComputedColumn;
|
import tech.ailef.dbadmin.annotations.ComputedColumn;
|
||||||
@ -128,8 +129,13 @@ public class DbObjectSchema {
|
|||||||
public List<DbField> getSortedFields() {
|
public List<DbField> getSortedFields() {
|
||||||
return getFields().stream()
|
return getFields().stream()
|
||||||
.filter(f -> {
|
.filter(f -> {
|
||||||
return f.getPrimitiveField().getAnnotation(OneToMany.class) == null
|
boolean toMany = f.getPrimitiveField().getAnnotation(OneToMany.class) == null
|
||||||
&& f.getPrimitiveField().getAnnotation(ManyToMany.class) == null;
|
&& f.getPrimitiveField().getAnnotation(ManyToMany.class) == null;
|
||||||
|
|
||||||
|
OneToOne oneToOne = f.getPrimitiveField().getAnnotation(OneToOne.class);
|
||||||
|
boolean mappedBy = oneToOne != null && !oneToOne.mappedBy().isBlank();
|
||||||
|
|
||||||
|
return toMany && !mappedBy;
|
||||||
})
|
})
|
||||||
.sorted((a, b) -> {
|
.sorted((a, b) -> {
|
||||||
if (a.isPrimaryKey() && !b.isPrimaryKey())
|
if (a.isPrimaryKey() && !b.isPrimaryKey())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user