I know it is not new question in this forum but I am very confused what should i do.
Problem: I am developing one application with spring mvc + hibernate. For server side validation I am using #valid annotation in controller and #null and #notNull annotation in my bean.
e.g
public class User implements Serializable {
private static final long serialVersionUID = 2158419746939747203L;
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long userId;
#Column(name="USERNAME", unique = true)
#NotEmpty #NotNull #Size(min=6, max=20)
private String username;
#Column(name="PASSWORD")
#NotEmpty #NotNull #Size(min=6, max=20)
private String password;
This validation is happening fine and data is also saving in DB.
But I want to validate unique constraint,referential integrity and other constraint using annotation without any validator class.
Is it possible? if no, then what is best and easiest way to to do it(less coding)? I will appreciate if framework will do it for me.
Saurabh,
For unique constraint in table,
#Id
You will be able to enforce referential integrity via hibernate annotations as well
eg.
#OneToOne(mappedBy = "foo")
Here is an example post
Referential integrity with One to One using hibernate
Here is a very detailed tutorial also exploring the same:
http://www.journaldev.com/2882/hibernate-tutorial-for-beginners-using-xml-annotations-and-property-configurations
You could write a "CustomUniqueConstraintValidator" kinda like mentioned in
http://www.journaldev.com/2668/spring-mvc-form-validation-example-using-annotation-and-custom-validator-implementation
You can also pass in paramters from the annotation to the custom validator.
eg.
#CustomValidDate("columnName")
To make a generic class that applies for any field /column
1. YOu can write a generic custom validator
2. use annotaiton parameters (on each class attribute) to pass in the table name and column name.
3. Then in the validator you can use the table name, column name to apply your validation logic (unique etc).
Thanks,
Paul
Related
I use the date validaton using the #Future annotation.
#NotNull
#DateTimeFormat(pattern="yyyy-MM-dd")
#Column(name = "FROM")
#Temporal(TemporalType.DATE)
#Future
private Date from;
#NotNull
#Column(name = "FOO")
private String foo;
I perform CRUD operations using Rest API. The requirement is the from date will be in future - after the entity is being created (today). However, the time changes and in case of changing the field foo using ex. PUT method, the validation won't pass.
#PutMapping(value = "/{id}")
public ResponseEntity<?> put(
#Valid #RequestBody MyEntity myEntity,
#PathVariable("id") int id)
{
... update entity based on id
}
When I call this method in the far future (after the from value persisted), the validation doesn't let me perform the operation, because the field from is no more valid.
There is a simple in-built solution to trigger a certain validation only on create event?
I have been thinking over creating the own cross-field validation through annotation, however I am not able to determine the creation based on other fields.
You can use Grouping Constraints, to restrict which validation set to use for: pre-persist, pre-update, pre-remove and ddl(For database schema).
So to validate from field just for persist operation and ignore it for put(update), you may:
Add an interface e.g. GroupFuture:
package com.example.entity;
public interface GroupFuture {}
In your MyEntity, I think you should also add #NotNull constraint as #Future consider null as valid value:
//...
//Maybe #NotNull
#Future(groups = GroupFuture.class)
private Date from;
//...
Finally, if you've configured hibernate using:
persistence.xml, add this line in the persistence-unit setting:
<property name="javax.persistence.validation.group.pre-persist" value="javax.validation.groups.Default, com.example.GroupFuture">
Programmatically:
// If you're using pure hibernate
Configuration configuration = new Configuration().setProperty("javax.persistence.validation.group.pre-persist", javax.validation.groups.Default, com.example.GroupFuture);
`
// If you're using JPA/hibernate
entityManagerFactory.getJpaPropertyMap().put("javax.persistence.validation.group.pre-persist", javax.validation.groups.Default, com.example.GroupFuture);
Useful reading(even it's for hibernate 3.6): Chapter 23. Additional modules
I am using Bean Validation constraints to validate class instances at run time. I have many DTOs where each has multiple fields often with a common constraint. I want to add a constraint to the class so that it applies to all the properties of the class. (As lombok #NotNull constraint).
e.g
class Person {
#NotNull
private String name;
#NotNull
private String address;
#NotNULL
private String contact;
}
I want to make it something like this.
#NotNull
class Person {
private String name;
private String address;
private String contact
}
You cannot do this with plain Bean Validation. So just adding #NotNull to the class won't work.
One potential approach could be to utilize XML configuration. The idea would be to have your own annotation MyNotNull. Your framework would need to scan for these annotations and build the programmatic configuration for the class in question. This could for example be done via a annotation processor during compile time. Once you have the constraint mapping XML files add them to your jar and reference them in validation.xml. That's just a basic idea. Personally, I am not sure whether it is worth the effort.
I have solr schema where almost every field is required=true.
I am using following POJO to persist data in solr
#Field(value = "id")
private String id;
#Field(value = "entity_id")
private Long entityId;
...
Now before sending it to solr, I am currently checking explicitly each field for null. Is there any annotation like #NotNull or #Field attribute like required=true so that I need not to check them ?
Unfortunately, I do not believe that SolrJ has this capability. (Source - I looked at the source code. Field does not have this defined, nor are there other beans that might be useful.)
How to implement different constraints for different requests? For example, there is User class:
public class User extends Model{
#Required
#Email
#Id
public String email;
#Required
#Column(length = 50)
public String firstname;
#Required
#Column(length = 50)
public String lastname;
#Required
public String password;
}
When I create a new user, all constraints are required. But when I update user information, I don't need the password constraint.
Should I create separate classes for createUser() and updateUser() actions?
Is there any way I can use just one class?
It is bad practise to mix "back-end entity" annotations with "front-end entity" annotations. Create separate class for inserting user and updating user with #Required annotations accordingly. Remove front-end annotations from User entity and leave only JPA annotations like #Id #Column etc.
As Play's validation framework conforms to the Java bean validation specification (JSR-303), you can use the validation groups feature that is part of the spec. This is exactly what you are looking for - a neat way of enforcing different validation rules for different actions. You can see an example of how to use it in code in this answer I gave to a similar question.
I have a set of JPA POJO's that contain annotations required for mapping to my domain. I also want to expose some REST services that will interact with those domain objects.
My current task is to create an android application to access these REST services. I am not able to use the domain object due to the JPA annotations they contain. The Dalvik compiler complains.
So I am looking for a strategy to be able to leverage these domain objects in a way that an Android project can also use those objects and not have to duplicate those POJO's.
Victor's suggestion to externalise the JPA mappings to XML rather than use annotations would surely work, but might be inconvenient if you're getting your JPA objects from tooling that only generates annotations.
I assume that you need on the client side Java classes that match the objects you will serialise in your REST services.
It is possible, but very tedious, to create DTO objects - POJOs exactly matching the JPA objects with suitable constructors from the JPA objects. This seems like an undue amount of effort.
It must be possible to write a source-code processor to strip the annotations from the Java. I don't think a simple regex scripting solution will work, I guess that truly parsing the source is necessary, so I hesitate to guess how much work this would be. However according to this question's answers the basic set of tools is available. I would start with this approach.
I could work out with following strategy.
This strategy works very well when you dont want fetch whole collection , or fetch with some addition criteria,
, you may retrieve it(collection relation) with named query.
use separate DAO for CRUD operation on JOIN table of many to many relation
e.g.
User can have many accounts and account can be shared by many users.
create domain models/ DAO for all the three tables,
use relation mapping for just retrieval and for DDL use individual properties.
#Entity
#Table(name="account" )
public class Account {
#Id (name="accountid")
private Long accountId;
#Column
private String type;
// removed #OneToMany as it causes issue while serializing to xml
#Transient
private Collection accountUsers;
//rest of the properties n geter setter goes here
}
#Entity
#Table(name="user")
public class User {
#Id(name="userid")
private Long userId;
#Column
private String name;
// by making transient jpa / hibernate does not initialize it with proxy.. so it remains null
/* you can populate this property using named query whenever required .*/
#Transient
private Collection userAccounts;
// rest of the properties n getter setter goes here
}
#Entity
#Table(name="AccountUser")
public class AccountUser {
// whatever your strategy to implement primary key here ,
#Id (name="accountuserid")
private Long accountUserId;
/* please note this annotation , made insertable/updatable false , relation defined just for fetching relation
*/
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "accountid", referencedColumnName = "accountid", insertable = false, updatable = false)
private Account account;
// look at insertable / updatable properties its turned off
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "userid", referencedColumnName = "userid", insertable = false, updatable = false)
private User user;
//
#Column ( name = "userid" )
private Long userId;
#Column ( name = "accountid" )
private Long accountId;
#Column ( name="opendate")
private Date opendate;
}
/* use separate dao to save above beans */
// somthing like this
public class AccountDAOImpl extends GenericDAOImpl implements AccountDAO {
}
public class UserDAOImpl extends GenericDAOImpl implements UserDAO {
}
public class AccountUserDAOImpl extends GenericDAOImpl implements AccountUserDAO {
}
I tried to explain if need any clarification kindly revert back. thanks