In my application, i have these three classes
#Entity
#Indexed
public class CpamEntity {
#Id
private String externalId;
#Field
private String cgr;
#ElementCollection
private Set<AttachmentEntity> attachments;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "externalId")
private Set<DataEntity> data;
}
#Entity
#Indexed
public class DataEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String internalId;
#Field
private String number;
#JsonIgnore
#ManyToOne
#JoinColumn(name = "externalId", updatable = false)
private FrameworkEntity frameworkEntity;
}
the below code is to insert DataEntity (X) into CpamEntity, then get all attachments CpamEntity by IdChild and insert the same DataEntity (X) in them
the problem is the first insertion doesn't happen, and the attachments CpamEntity insered
public void on(Event event) {
CpamEntity cpamEntity = getCpamEntity(event.externalId);
if (cpamEntity != null) {
Set<DataEntity> datas = cpamEntity.getData();
datas.add(new DataEntity(event.internalId, event.number));
cpamEntity.setData(datas);
repository.save(cpamEntity); // not saved
if (CollectionUtils.isNotEmpty(cpamEntity.getAttachments())) {
cpamEntity.getAttachments().forEach(attachment -> {
cpamRepositoryentity = repository.findByCgr(attachment.getIdChild());
if (entity != null) {
Set<Entity> dataEntities = entity.getData();
dataEntities.add(new DataEntity(event.internalId, event.number));
entity.setData(dataEntities);
cpamRepository.save(entity); // saved
}
});
}
}
}
Related
Processor.java
#Entity
public class Processor {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private boolean running;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "firmware_id", referencedColumnName = "id")
private Firmware firmware;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
...
public Firmware getFirmware() {
return firmware;
}
public void setFirmware(Firmware firmware) {
this.firmware = firmware;
}
}
Firmware.java
#Entity
public class Firmware {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String version;
private String filename;
//Getter & Settger
}
ProcessorRepository.java
public interface ProcessorRepository extends CrudRepository<Processor, Integer> {
}
ProcessorController.java
...
#PutMapping(path = "/") // Map ONLY POST Requests
public #ResponseBody
Map<String, Object> addProcessor(#RequestBody Processor p) {
System.out.println("Put: " + p.getId());
processorRepository.save(p);
// I want to access : p.firmware_id;
// ex) p.setFirmware_id(8)
// ex) int tmp = p.getFirmware_id();
return Collections.singletonMap("success", true);
}
...
Below code is possible in java/spring-boot/hibernate?
// ex) p.setFirmware_id(8)
// ex) int tmp = p.getFirmware_id();
You can try to correct your mapping in this way:
#Entity
public class Processor {
// ...
// #NotFound ( action = NotFoundAction.IGNORE )
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "firmware_id", referencedColumnName = "id", insertable = false, updatable = false)
private Firmware firmware;
#Column(name = "firmware_id")
private Integer firmwareId;
// ...
}
and then set firmware_id via firmwareId.
Probably for this case you should use also #NotFound annotation (see this section of the documentation)
p.getFirmware().getId() or p.getFirmware().setId(id) whatever works
I want to have a simple parent children relationship but somehow it does not work and I don't get what is missing.
Parent Mapper Interface (adding uses = {LayerMapper.class} does not change anything):
#Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
#DecoratedWith(MlpConfigMapperDecorator.class)
public interface MlpConfigMapper {
#Mapping(target = "epochNumber", source = "epochs")
#Mapping(target = "activationFunction", ignore = true)
MlpConfig toEntity(CustomMlpConfigRequest mlpConfigDto);
}
Parent decorator according to this answer (https://stackoverflow.com/a/60217018/10565504):
public abstract class MlpConfigMapperDecorator implements MlpConfigMapper {
#Autowired
#Qualifier("delegate")
private MlpConfigMapper delegate;
#Autowired
private ActivationFunctionService activationFunctionService;
#Override
public MlpConfig toEntity(CustomMlpConfigRequest mlpConfigDto) {
MlpConfig mlpConfig = delegate.toEntity(mlpConfigDto);
mlpConfig.setActivationFunction(activationFunctionService.findByType(mlpConfigDto.getActivationFunction()));
return mlpConfig;
}
}
The Parent DTO:
public class CustomMlpConfigRequest {
private String name;
private String description;
private int batchSize;
private int epochs;
private List<LayerDto> layers;
private String activationFunction;
}
The Child DTO:
public class LayerDto {
public String type;
public int orderNumber;
public int neuronsNumber;
}
Parent Entity:
public class MlpConfig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String description;
private int batchSize;
private int epochNumber;
#JoinColumn(nullable = false, name = "activationFunction_id")
#ManyToOne(fetch = FetchType.LAZY)
private ActivationFunction activationFunction;
#JsonManagedReference
#Column(nullable = false)
#OneToMany(mappedBy = "mlpConfig", cascade = CascadeType.ALL)
private List<Layer> layers;
#ManyToOne(fetch = FetchType.LAZY)
private User user;
private Date lastUpdated;
}
Child Entity:
public class Layer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private ELayer type;
private int neuronsNumber;
private int orderNumber;
#EqualsAndHashCode.Exclude
#ToString.Exclude
#ManyToOne(fetch = FetchType.LAZY, optional=false)
#JoinColumn(name = "mlpConfig_id", nullable=false)
#JsonBackReference
private MlpConfig mlpConfig;
}
Generated Child Entity Mapper Method (setChildren or setMlpConfig() in my case is missing):
#Override
public LayerDto layerToDto(Layer layer) {
if ( layer == null ) {
return null;
}
LayerDto layerDto = new LayerDto();
if ( layer.getType() != null ) {
layerDto.setType( layer.getType().name() );
}
layerDto.setOrderNumber( layer.getOrderNumber() );
layerDto.setNeuronsNumber( layer.getNeuronsNumber() );
return layerDto;
}
How do I get the mapper to set the parent in the child?
do you have Layer toEntity(LayerDto layerDto);
Also, on setter of layers on entity class, you should say, layers.forEach (layer -> layer.setmlpConfig(this));
Did you do that setting job? If you don't, layers of mplConfig entity can always be null when you try to get it.
In the end I fixed it myself. I don't know if it is best practice and probably the mapper should do it without manual help but at least it works:
public abstract class MlpConfigMapperDecorator implements MlpConfigMapper {
#Autowired
#Qualifier("delegate")
private MlpConfigMapper delegate;
#Autowired
private ActivationFunctionService activationFunctionService;
#Override
public MlpConfig mlpConfigToEntity(CustomMlpConfigRequest mlpConfigDto) {
MlpConfig mlpConfig = delegate.mlpConfigToEntity(mlpConfigDto);
mlpConfig.setActivationFunction(activationFunctionService.findByType(mlpConfigDto.getActivationFunction()));
//this is the difference. I set the config for the layer manually
mlpConfig.getLayers().forEach(e -> e.setMlpConfig(mlpConfig));
return mlpConfig;
}
}
I have two entities lets call them Categories and Products. These two entities are mapped by a many to many relationship.
My problem is that i am trying to get category information from products. Trying this results in empty categories.
This is my code :
PersistenceEntity
#MappedSuperclass
public class PersistenceEntity implements Serializable {
private static final long serialVersionUID = 4056818895685613967L;
// Instance Variables
#Id
#Column(unique = true)
#GeneratedValue(strategy = GenerationType.TABLE)
protected Long id;
#JsonIgnore
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
protected Date creationDate = new Date();
...Getters and Setters omitted for brevity
}
Category
#Entity
#Table(name = "category")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Category extends PersistenceEntity{
private static final long serialVersionUID = 1L;
#Column(nullable = false)
private String categoryName;
#Column(nullable = false)
private Boolean active;
#Column(nullable = true)
private String picture;
#JsonIgnore
private MetaData metadata;
#ManyToMany(fetch = FetchType.EAGER,mappedBy = "categories")
private Set<Product> products;
...Getters and Setters omitted for brevity
}
Product
#Entity
#Table(name = "products",uniqueConstraints = { #UniqueConstraint(columnNames = "productCode")})
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product extends PersistenceEntity {
private static final long serialVersionUID = 8727166810127029053L;
#Column(name = "product_name")
private String name;
private String productImageUrl;
#JsonIgnore
#ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
#JoinTable(name="category_products",
joinColumns={#JoinColumn(name="product_id", unique = false)},
inverseJoinColumns={#JoinColumn(name="category_id", unique = false)})
private Set<Category> categories;
...Getters and Setters omitted for brevity
}
ProductServiceImplementation
#Service
public class ProductService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
private ProductRepository productRepository;
public List<Product> getProductsByShopId( Long id) {
List<Product> productList = new ArrayList<>();
productList = productRepository.findByShopId(id);
return productList;
}
public Set<Long> getCategoryIds(List<Product> products){
Set<Long> categoriesIDs = new HashSet<Long>();
for (Product product : products) {
product.getCategories().forEach(category -> {
categoriesIDs.add(category.getId());
});
}
return categoriesIDs;
}
}
The problem is getting the categoryIds that are mapped to the list of products.
How can i get CategoryIds from Product. My getCategoryIds function returns empty always
public Set<Long> getCategoryIds(List<Product> products){
Set<Long> categoriesIDs = new HashSet<Long>();
for (Product product : products) {
product.getCategories().forEach(category -> {
categoriesIDs.add(category.getId());
});
}
return categoriesIDs;
}
I'm doing a registration and I have the fields
Nome:
Data de Nascimento:
Inscrição Estadual:
Nome Responsável:
CPF Responsável:
Cep:
Bloco:
Número:
when i saving, I can not write data from the PessoasEnderecos class, the other data is recording normal. I'm getting all the data on the screen so much that I debugged the browser to see ..
It shows no error. Does anyone know what I'm missing ??
my class Pacientes
#Entity
#Table(name = "pacientes", schema = "sau")
public class Pacientes implements Serializable {
private static final long serialVersionUID = 5776384003601026304L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idPaciente")
private Long idPaciente;
#JoinColumn(name="idPessoa")
#ManyToOne(cascade = CascadeType.ALL)
private Pessoas pessoa;
#Column(name = "nomeResponsavel")
private String nomeResponsavel;
#Column(name = "cpfResponsavel")
private String cpfResponsavel;
public Pacientes() {
}
//gets and sets
}
my class Pessoas
#Entity
#Table(name = "pessoas", schema="glb")
public class Pessoas implements Serializable {
private static final long serialVersionUID = -4042023941980758267L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
private Long idPessoa;
#Temporal(TemporalType.DATE)
private Date dataNascimento;
private String inscricaoEstadual;
private String inscricaoMunicipal;
private String nome;
public Pessoas() {
}
//gets and sets
}
#Entity
#Table(name = "pessoas_enderecos" ,schema="glb")
public class PessoasEnderecos implements Serializable {
private static final long serialVersionUID = -2560542418318988673L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idPessoaEndereco;
private String bloco;
private String cep;
private String numero;
#JoinColumn(name="idPessoa")
#ManyToOne(optional = false, cascade = CascadeType.ALL)
private Pessoas pessoa;
public PessoasEnderecos() {
}
//gets and sets
}
my methods
class Controller
#RequestMapping(method = RequestMethod.POST, value = "/pacientes")
public Pacientes cadastrarPacientes(#RequestBody Pacientes pac) {
return pacientesService.cadastrar(pac);
}
class service
public Pacientes cadastrar(Pacientes pacientes){
return pacRepository.save(pacientes);
}
class repository
public interface PacientesRepository extends JpaRepository<Pacientes, Integer> {
}
You should also add the linkage #OneToMany in Pacientes:
public class Pacientes implements Serializable {
...
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "pessoa")
#PrimaryKeyJoinColumn
private List<PessoasEnderecos> pessoasEnderecos = new ArrayList<>();
Update:
and your JSON should be something like this:
{
"nomeResponsavel": "abc",
"pessoasEnderecos": [
{
"bloco": "sdds",
"cep": "sdasdsad",
"numero": "sdasdsa"
}
]
}
I have following JPA entity structure.
#Entity
#Table(name = "PARENT_DETAILS")
class Parent{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "parent_details_seq")
#SequenceGenerator(name = "parent_details_seq", sequenceName = "PARENT_DETAILS_SEQ", allocationSize = 1)
#Column(name = "PARENT_ID")
private long parentId;
#Column(name = "PARENT_NAME")
private String parentName;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "childPK.parent", cascade = CascadeType.ALL)
private Set<Child> child;
//setters and getters
}
#Entity
#Table(name = "CHILD_DETAILS")
public class Child {
private ChildPK childPK;
public void setProgramProcessesPK(ChildPK childPK) {
this.childPK = childPK;
}
#EmbeddedId
public ChildPK getChildPK() {
return childPK;
}
}
#Embeddable
public class ChildPK implements Serializable {
private static final long serialVersionUID = 1L;
private Parent parent;
private long childId;
#Column(name = "CHILDID")
public long getChildId() {
return childId;
}
public void setChildId(long childId) {
this.childId = childId;
}
#ManyToOne
#JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID", nullable = false)
public ParentDetails getParent() {
return parent;
}
}
I want to write a JPA query which will return the PARENT_NAME and the count of all children for a given parent_id.
Tthe only solution I can think of is joining and writing a complex criteria query.
I cannot think of a way to get the result using a simple JPA query.
Is there an easier way to do this?
Have you tried SIZE? Something like "Select parent.parentName, Size(parent.child) from Parent parent" might work.
You can use JPA Named Query such as this:
private static class ParentChildsNumber {
public String parentName;
public Integer childsNum;
public ParentChildsNumber(String parentName, Integer childsNum) {
this.parentName = parentName;
this.childsNum = childsNum;
}
}
#NamedQuery(name="getParentChildsNumberQuery", query="SELECT NEW ParentChildsNumber(p.parentName, SIZE(p.child)) FROM Parent p WHERE p.parentId = :parentId GROUP BY p.parentId, p.parentName")
Use it in your code in the following way:
#PersistenceContext(unitName="YourPersistentUnit")
private EntityManager em;
em.createNamedQuery("getParentChildsNumberQuery", ParentChildsNumber.class).setParameter("parentId", parentId).getSingleResult();