Hibernate issue - missing association in #JoinTable - java

I'm using Spring and Hibernate. I have following JPA mapping:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "chg_type")
public abstract class EntitlementChange extends AbstractEntity<Long> {
protected static List<Argument<?>> copy(List<Argument<?>> arguments) {
return arguments.stream()
.map(Argument::getCopy)
.collect(toList());
}
protected EntitlementChange(List<Argument<?>> arguments) {
super();
this.arguments = copy(arguments);
}
#Id
#GeneratedValue(generator = SequenceOf.ENTITLEMENT_CHANGE_IDS)
#SequenceGenerator(name = SequenceOf.ENTITLEMENT_CHANGE_IDS, sequenceName = SequenceOf.ENTITLEMENT_CHANGE_IDS, allocationSize = 50)
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable
private List<Argument<?>> arguments;
}
And entity which inherits from EntitlementChange class.
#Entity
#DiscriminatorValue(EntitlementModification.DISCRIMINATOR)
public class EntitlementModification extends EntitlementChange {
public static final String DISCRIMINATOR = "modify";
public EntitlementModification(List<Argument<?> arguments) {
super(arguments);
}
}
The problem is that when I'm creating new EntitlementModification object with list of arguments and saving it to database using transaction:
#Transactional
public EntitlementChange createEntitlementChange(List<Argument<?>> arguments) {
EntitlementChange change = new EntitlementModification(arguments);
return entitlementChangeRepository.save(change);
}
I get EntitlementChange object with new ID which contain arguments list with assigned ID's too. When we look to the database, we can see that arguments entries are created, EntitlementChange entry is created, but association in joining table is not created. So when I'm getting EntitlementChange object using repository, arguments are null. Argument class:
#Entity
#DiscriminatorColumn(name = "arg_type", discriminatorType = DiscriminatorType.STRING)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#JsonTypeInfo(include = As.PROPERTY, property = "type", use = JsonTypeInfo.Id.NAME)
#JsonSubTypes({
#Type(value = LongStringArgument.class, name = LongStringArgument.DISCRIMINATOR),
#Type(value = StringArgument.class, name = StringArgument.DISCRIMINATOR),
#Type(value = BooleanArgument.class, name = BooleanArgument.DISCRIMINATOR),
#Type(value = SelectOneArgument.class, name = SelectOneArgument.DISCRIMINATOR),
#Type(value = MultiSelectArgument.class, name = MultiSelectArgument.DISCRIMINATOR),
#Type(value = IntegerArgument.class, name = IntegerArgument.DISCRIMINATOR)
})
public abstract class Argument<T> extends AbstractEntity<Long> {
#Id
#GeneratedValue(generator = SequenceOf.ARGUMENT_IDS)
#SequenceGenerator(name = SequenceOf.ARGUMENT_IDS, sequenceName = SequenceOf.ARGUMENT_IDS, allocationSize = 50)
private Long id;
private String name;
protected Argument() {
super();
}
public Argument(String name) {
super();
this.name = name;
}
#Override
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract T getValue();
#JsonIgnore
public abstract Argument<T> getCopy();
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Argument))
return false;
Argument<?> argument = (Argument<?>) o;
return new EqualsBuilder()
.append(getName(), argument.getName())
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getName())
.toHashCode();
}
}
What could be a reason of this strange behaviour?

Related

Vaadin flow Grid items duplicate rows

Vaadinversion: 14.4.1
spring-boot-starter-parent: 2.2.10RELEASE
I have two items in my grid. These two items looks like:
Kontakt{id=11657f9e-c4f4-414f-aab2-618252db9b06'vorname='test1'...
Kontakt{id=8da74f38-2072-4fb0-8c74-aede661f02b5'vorname='test'...
But the grid only displays only one items and so oft like the "itemslist.size()"
Also they react as "one row". So I can like on the first and both get selected.
These are my #Entity(s)
#Entity
#Table(name = "std_kunde")
#Data
public class Kunde extends Kontakt {
public Kunde() {
super();
}
#Override
public String toString() {
return super.toString();
}
}
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Data
public abstract class Kontakt extends BasicEntity {
private String vorname;
private String name;
...
public Kontakt() {
super();
}
#Override
public String toString() {
return "Kontakt{" +
"id=" + getId() + '\'' +
"vorname='" + vorname + '\'' +
...
'}';
}
}
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Data
public abstract class BasicEntity {
#Id
#GenericGenerator(name = "id_generator", strategy = "....KeyGenerator")
#GeneratedValue(generator = "id_generator")
#Column(length = 128)
private String id;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "create_date")
private Date createDate;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "modify_date")
private Date modifyDate;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "basicEntity")
private List<Anhang> anhangList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "basicEntity")
private List<Notiz> notizList;
public BasicEntity() {
anhangList = new ArrayList<>();
notizList = new ArrayList<>();
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public boolean equals(Object o){
if(null == o)
return false;
if(!(o instanceof BasicEntity))
return false;
BasicEntity b = (BasicEntity) o;
return b.getId().equals(this.getId());
}
}
And also the Grid code
#Autowired
private KundeService kundeService;
private Grid<Kunde> g;
public Dashboard() {
g = new Grid<>(Kunde.class);
g.addColumn(Kunde::getVorname).setHeader("Vorname");
g.setSizeFull();
setSizeFull();
add(g);
}
I tested to build a Grid based upon an other entiy and it worked like it should. Its like the first time I have this behaivor but I dont know how actually to debug it...
EDIT 29.10.2020 ---------------------------------------------------------------
This is the #Entity (Notiz) which works like expected.
UI-Code
private Grid<Kunde> g;
private Grid<Notiz> n;
public Dashboard() {
g = new Grid<>(Kunde.class);
g.addColumn(Kunde::getId).setHeader("ID");
g.addColumn(Kunde::getVorname).setHeader("Vorname");
g.setSizeFull();
n = new Grid<>(Notiz.class);
n.addColumn(Notiz::getId).setHeader("ID");
n.addColumn(Notiz::getTitel).setHeader("Titel");
n.setSizeFull();
setSizeFull();
add(g,n);
}
#PostConstruct
private void loadValues(){
g.setItems(kundeService.findAll());
n.setItems(notizService.findAll());
}
#Entity
#Table(name = "ld_notiz")
#Data
public class Notiz extends BasicEntitySystemFeatures {
private String titel;
#Column(length = 5000) //TODO
private String content;
private boolean abgeschlossen = false;
#Enumerated(EnumType.STRING)
private NOTIZ_TYP notizTyp;
public enum NOTIZ_TYP {
NOTIZ,
ERINNERUNG
}
#ManyToOne
private BasicEntity basicEntity;
public Notiz() {
super();
}
}
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Data
public abstract class BasicEntitySystemFeatures {
#Id
#GenericGenerator(name = "id_generator", strategy = "...KeyGenerator")
#GeneratedValue(generator = "id_generator")
#Column(length = 128)
private String id;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "create_date")
private Date createDate;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "modify_date")
private Date modifyDate;
public BasicEntitySystemFeatures() {
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public boolean equals(Object o){
if(null == o)
return false;
if(!(o instanceof BasicEntitySystemFeatures))
return false;
BasicEntitySystemFeatures b = (BasicEntitySystemFeatures) o;
return b.getId().equals(this.getId());
}

EmbeddableId should be mapped with insert="false" update="false"

I have the following entities: Match with embeddableId MatchKey and a polymorphic entity OrganisationMatch
Hibernate is blowing up with Repeated column in mapping for entity: net.satago.web.entities.OrganisationMatch column: referenceKind (should be mapped with insert="false" update="false")
I don't know what is wrong, can I not use #DiscriminatorColumn annotations on #EmbeddableIds parts and make them not insertable nor updatable?
It works fine if the column to discriminate by is not part of an #EmbeddableId but just a regular column on the Match entity.
#Embeddable
#ParametersAreNonnullByDefault
public class MatchKey implements Serializable
{
private static final long serialVersionUID = 7619427612022530146L;
#Column(insertable = false, updatable = false)
#Enumerated(STRING)
private MatchableEntityKind referenceKind;
private Long referenceId;
public MatchKey()
{
// For JPA
}
public MatchKey(OrganisationId organisationId)
{
this.referenceKind = ORGANISATION;
this.referenceId = organisationId.getId();
}
public MatchableEntityKind getReferenceKind()
{
return referenceKind;
}
public void setReferenceKind(MatchableEntityKind referenceKind)
{
this.referenceKind = referenceKind;
}
public Long getReferenceId()
{
return referenceId;
}
public void setReferenceId(Long referenceId)
{
this.referenceId = referenceId;
}
#Override
public boolean equals(Object obj)
{
if (obj instanceof MatchKey)
{
MatchKey that = (MatchKey) obj;
return this.referenceKind == that.referenceKind &&
Objects.equals(this.referenceId, that.referenceId);
}
return false;
}
#Override
public int hashCode()
{
return Objects.hash(referenceKind, referenceId);
}
}
#Entity
#Table(name = TABLE_NAME)
#Inheritance(strategy = SINGLE_TABLE)
#DiscriminatorColumn(name = "reference_kind", discriminatorType = DiscriminatorType.STRING)
#ParametersAreNonnullByDefault
public class Match implements EntityModel<MatchKey>
{
static final String TABLE_NAME = "matches";
#EmbeddedId
private MatchKey id;
#Version
private Long version;
... generic match columns
}
and
#Entity
#DiscriminatorValue(OrganisationMatch.REFERENCE_KIND)
#ParametersAreNonnullByDefault
public class OrganisationMatch extends Match
{
static final String REFERENCE_KIND = "ORGANISATION";
#JoinColumn(name = "reference_id")
#OneToOne(fetch = LAZY, optional = false)
private Organisation organisation;
public OrganisationMatch()
{
setReferenceKind(MatchableEntityKind.valueOf(REFERENCE_KIND));
}
public OrganisationMatch(OrganisationId organisationId)
{
super(new MatchKey(organisationId));
setReferenceKind(MatchableEntityKind.valueOf(REFERENCE_KIND));
}
public Organisation getOrganisation()
{
return organisation;
}
}

Throwing error while saving multiple oneToMany Entity relations in Hibernate

I am having an entity class which has two Entity class with one to many relationship. and there is one root parent entity which has ID variable which is being extended by all the entity. When i am trying to save MessagingEnablerCfg entity without initializing it's member variable(messagingProfiles and messagingSessions). it is getting saved. but if i will try to initialize the these set variable. it is throwing following error while doing save or update operation:
Caused by: java.sql.SQLException: Field 'messagingProfiles_id' doesn't have a default value
Note: if there is only one variable(either messagingProfiles or messagingSessions) in the MessagingEnablerCfg entity then it will work fine for saving or updating.
i feel it is weird but right now it is a big trouble for me.
Please find the below Entity class
#Entity
//#Indexed
#Proxy(lazy=false)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class MessagingConfigEntity{
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
//#Override
public String getId() {
return id;
}
}
another Entity class is:
#Entity
//#Indexed
#Proxy(lazy=false)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown=true)
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class MessagingEnablerCfg extends MessagingConfigEntity {
private String serviceName;
#OneToMany(cascade = { CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER)
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<MessagingProfileCfg> messagingProfiles = new HashSet<>();
//#OneToMany(cascade = { CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER)
#OneToMany(cascade = { CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.EAGER)
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<MessagingSessionCfg> messagingSessions = new HashSet<>();
public MessagingEnablerCfg(){
}
public MessagingEnablerCfg(String service){
this.serviceName = service;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public Set<MessagingSessionCfg> getMessagingSessions() {
return messagingSessions;
}
public void setMessagingSessions(Set<MessagingSessionCfg> messagingSessions)
{
this.messagingSessions = messagingSessions;
}
public Set<MessagingProfileCfg> getMessagingProfiles() {
return messagingProfiles;
}
public void setMessagingProfiles(Set<MessagingProfileCfg> messagingProfiles)
{
this.messagingProfiles = messagingProfiles;
}
public void addSession(MessagingSessionCfg session){
messagingSessions.add(session);
}
public void addProfile(MessagingProfileCfg profile){
messagingProfiles.add(profile);
}
}
Another Child class is:
#Entity
//#Indexed
#Proxy(lazy = false)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class MessagingSessionCfg extends MessagingConfigEntity{
private String sessionName;
private String provider;
public MessagingSessionCfg(){
}
public MessagingSessionCfg(String name,String provider){
this.sessionName = name;
this.provider = provider;
}
public String getSessionName() {
return sessionName;
}
public void setSessionName(String sessionName) {
this.sessionName = sessionName;
}
public String getProvider() {
return provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public String toString(){
return "sessionName:"+sessionName+" provider:"+provider;
}
}
Ans last child entity is:
#Entity
//#Indexed
#Proxy(lazy=false)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class MessagingProfileCfg extends MessagingConfigEntity {
private String profileId;
private String sourceAddress;
public MessagingProfileCfg(){
}
public MessagingProfileCfg(String profileId, String sourceAddress){
this.profileId = profileId;
this.sourceAddress = sourceAddress;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public String getSourceAddress() {
return sourceAddress;
}
public void setSourceAddress(String sourceAddress) {
this.sourceAddress = sourceAddress;
}
}

I get error: Invocation of init method failed; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity

I get error:
Invocation of init method failed; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.messagemanager.domain.User column: id (should be mapped with insert="false" update="false")
There are my Entities:
#MappedSuperclass
public abstract class BaseEntity{
#Id
#Column(nullable = false, unique = true, name = "id", insertable = false, updatable = false)
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
#Table(name = "User")
public class User extends BaseEntity implements Serializable{
#Column(name = UserFieldsKey.ID, length = 50, nullable = false)
private String name;
#Column(updatable = false, insertable = false)
#Transient
private List<Message> listMessage = new ArrayList<>();
public static class UserFieldsKey{
public static final String NAME = "name";
}
public User() {
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
public List<Message> getListMessage() {
return listMessage;
}
public void setListMessage(List<Message> listMessage) {
this.listMessage = listMessage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "Message")
public class Message extends BaseEntity implements Serializable{
#Column(name = MessageFieldsKey.MESSAGE, length = 500, nullable = false)
private String message;
#ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name="user")
private User user;
#Column(name = "id_user")
private Long id_user;
public Long getId_user() {
return id_user;
}
public void setId_user(Long id_user) {
this.id_user = id_user;
}
public static class MessageFieldsKey{
public static final String MESSAGE = "mes";
}
public String getMessage() {
return message;
}
public User getUser() {
return user;
}
public Message() {
}
public Message(String message, User user) {
this.message = message;
this.user = user;
}
public void setMessage(String message) {
this.message = message;
}
public void setUser(User user) {
this.user = user;
}
}
Any ideas?
P.S. thanks a lot!
It looks like that's because you have this:
#ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name="user")
private User user;
which will map to User.id; and in Message you already have an id since you are extending BaseEntity
Issue solved) I mistook in relationship between tables.

Multiple beans validation inside containing bean with different group interfaces

I have problem with validation a very specific beans.
Let me give you some code first:
#Entity
#Table(name = "customers", schema = "public", uniqueConstraints = #UniqueConstraint(columnNames = {"cus_email" }))
public class Customers extends ModelObject implements java.io.Serializable {
private static final long serialVersionUID = -3197505684643025341L;
private long cusId;
private String cusEmail;
private String cusPassword;
private Addresses shippingAddress;
private Addresses invoiceAddress;
#Id
#Column(name = "cus_id", unique = true, nullable = false)
#SequenceGenerator(name = "cus_seq", sequenceName = "customers_cus_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cus_seq")
#NotNull
public long getCusId() {
return cusId;
}
public void setCusId(long cusId) {
this.cusId = cusId;
}
#NotEmpty
#Size(min=5, max=255)
#Email
#Column(name = "cus_email", unique = true, nullable = false, length = 255)
public String getCusEmail() {
return cusEmail;
}
public void setCusEmail(String cusEmail) {
this.cusEmail = cusEmail;
}
#NotNull
#Column(name = "cus_password", nullable = false)
public String getCusPassword() {
return cusPassword;
}
public void setCusPassword(String cusPassword) {
this.cusPassword = cusPassword;
}
#NotNull
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cus_shipping_adr_id", nullable = false)
#Cascade(value = CascadeType.ALL)
#Valid
public Addresses getShippingAddress() {
return shippingAddress;
}
public void setShippingAddress(Addresses cusShippingAddress) {
this.shippingAddress = cusShippingAddress;
}
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cus_invoice_adr_id", nullable = true)
#Cascade(value = CascadeType.ALL)
#Valid
public Addresses getInvoiceAddress() {
return invoiceAddress;
}
public void setInvoiceAddress(Addresses cusInvoiceAddress) {
this.invoiceAddress = cusInvoiceAddress;
}
}
As you can see, I have here two address fields - one for shipping address, the other for invoice address.
The validation for each type of address should be different, as e.g. I don't need VAT number in shipping address, but I may want that in invoice.
I used groups to perform different validation on invoice address and shipping address which works OK if I do manual validation of address field.
But now I'd like to validate whole Customer object with addresses (if available).
I tried to do that with code below:
private void validateCustomerData() throws CustomerValidationException {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Customers>> constraintViolations;
constraintViolations = validator.validate(customer, Default.class, InvoiceAddressCheck.class, ShippingAddressCheck.class);
if (!constraintViolations.isEmpty()) {
throw new CustomerValidationException(3, Message.CustomerDataException, constraintViolations);
}
}
Of course this doesn't work as it supposed, since both validations are run on both instances of address objects inside customer object, so I get errors in shipping address from InvoiceAddressCheck interface and errors in invoice address from ShippingAddressCheck.
Here is shortened declaration of Addresses bean:
#Entity
#Table(name = "addresses", schema = "public")
#TypeDef(name = "genderConverter", typeClass = GenderConverter.class)
public class Addresses extends ModelObject implements Serializable{
private static final long serialVersionUID = -1123044739678014182L;
private long adrId;
private String street;
private String houseNo;
private String zipCode;
private String state;
private String countryCode;
private String vatNo;
private Customers customersShipping;
private Customers customersInvoice;
public Addresses() {}
public Addresses(long adrId) {
super();
this.adrId = adrId;
}
#Id
#Column(name = "adr_id", unique = true, nullable = false)
#SequenceGenerator(name = "adr_seq", sequenceName = "adr_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "adr_seq")
#NotNull
public long getAdrId() {
return adrId;
}
public void setAdrId(long adrId) {
this.adrId = adrId;
}
#NotNull
#Column(name = "adr_street", nullable = false)
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
#NotEmpty(groups = ShippingAddressCheck.class)
#Column(name = "adr_house_no")
public String getHouseNo() {
return houseNo;
}
#NotEmpty(groups = ShippingAddressCheck.class)
#Column(name = "adr_zip_code")
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
#Column(name = "adr_vat_no")
#NotEmpty(groups = InvoiceAddressCheck.class)
public String getVatNo() {
return vatNo;
}
public void setVatNo(String vatNo) {
this.vatNo = vatNo;
}
#OneToOne(fetch = FetchType.LAZY, mappedBy = "shippingAddress")
public Customers getCustomersShipping() {
return customersShipping;
}
public void setCustomersShipping(Customers customersShipping) {
this.customersShipping = customersShipping;
}
#OneToOne(fetch = FetchType.LAZY, mappedBy = "invoiceAddress")
public Customers getCustomersInvoice() {
return customersInvoice;
}
public void setCustomersInvoice(Customers customersInvoice) {
this.customersInvoice = customersInvoice;
}
}
Is there any way to run the validation, so that invoiceAddress is validated with InvoiceAddressCheck group and shippingAddress validated with ShippingAddressCheck group, but run during validation of Customer object?
I know that I can do it manually for each subobject, but that is not the point in here.
Temp solution for now is to write custom validation for invoice field, so it checks only InvoiceAddressCheck.
Here is the code I have
Annotation:
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = {InvoiceAddressValidator.class })
public #interface InvoiceAddressChecker {
String message() default "Invoice address incorrect.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator:
public class InvoiceAddressValidator implements ConstraintValidator<InvoiceAddressChecker, Addresses> {
#Override
public void initialize(InvoiceAddressChecker params) {
}
#Override
public boolean isValid(Addresses invoiceAddress, ConstraintValidatorContext context) {
// invoice address is optional
if (invoiceAddress == null) {
return true;
}
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Addresses>> constraintViolations;
constraintViolations = validator.validate(invoiceAddress, Default.class, InvoiceAddressCheck.class);
if (constraintViolations.isEmpty()) {
return true;
} else {
context.disableDefaultConstraintViolation();
Iterator<ConstraintViolation<Addresses>> iter = constraintViolations.iterator();
while (iter.hasNext()) {
ConstraintViolation<Addresses> violation = iter.next();
context.buildConstraintViolationWithTemplate(violation.getMessage()).addNode(
violation.getPropertyPath().toString()).addConstraintViolation();
}
return false;
}
}
}
And model annotation:
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cus_invoice_adr_id", nullable = true)
#Cascade(value = CascadeType.ALL)
#InvoiceAddressChecker
public Addresses getInvoiceAddress() {
return invoiceAddress;
}
It's not really great solution, but it does what I need.
If you figure out better solution, please let me know :)

Categories

Resources