After starting the program (launching TomCat) there are no tables created in the schema, but the table "player" has to be created automatically.
I checked hibernate config, but can't find where is the problem.
I've tried changing hbm2ddl.auto to hibernate.hbm2ddl.auto (also create, create-drop etc.) but it didn't help.
If there are any ideas, please let me know. Thanks.
Entity class:
package com.game.entity;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(schema = "rpg", name = "player")
public class Player {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name", length = 12, nullable = false)
private String name;
#Column(name = "title", length = 30, nullable = false)
private String title;
#Column(name = "race", nullable = false)
#Enumerated(EnumType.ORDINAL)
private Race race;
#Column(name = "profession", nullable = false)
#Enumerated(EnumType.ORDINAL)
private Profession profession;
#Column(name = "birthday", nullable = false)
private Date birthday;
#Column(name = "banned", nullable = false)
private Boolean banned;
#Column(name = "level", nullable = false)
private Integer level;
public Player() {
}
public Player(Long id, String name, String title, Race race, Profession profession, Date birthday, Boolean banned, Integer level) {
this.id = id;
this.name = name;
this.title = title;
this.race = race;
this.profession = profession;
this.birthday = birthday;
this.banned = banned;
this.level = level;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Race getRace() {
return race;
}
public void setRace(Race race) {
this.race = race;
}
public Profession getProfession() {
return profession;
}
public void setProfession(Profession profession) {
this.profession = profession;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Boolean getBanned() {
return banned;
}
public void setBanned(Boolean banned) {
this.banned = banned;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
}
Repository class:
package com.game.repository;
import com.game.entity.Player;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.NativeQuery;
import org.springframework.stereotype.Repository;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Optional;
#Repository(value = "db")
public class PlayerRepositoryDB implements IPlayerRepository {
private final SessionFactory sessionFactory;
public PlayerRepositoryDB() {
Configuration configuration = new Configuration().configure().addAnnotatedClass(Player.class);
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
#Override
public List<Player> getAll(int pageNumber, int pageSize) {
try(Session session = sessionFactory.openSession()){
NativeQuery<Player> nativeQuery = session.createNativeQuery("SELECT * FROM rpg.player", Player.class);
nativeQuery.setFirstResult(pageNumber * pageSize);
nativeQuery.setMaxResults(pageSize);
return nativeQuery.list();
}
}
Hibernate configuration:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/rpg</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">1234</property>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
Full project code with pom.xml is available by link:
https://github.com/gamlethot/project-hibernate-1
1-Hibernate does not recognize your repository. You should not mark repo classes as #Repository because they are not interfaces and in your example they are working like a service. So they can be #Service.
2-Do not implement IPlayerRepository. Mark it as #Repository and just autowire it to your service classes (or use constructor injection and just use like a variable)
Like:
#Service
public class PlayerRepositoryDB {
private IPlayerRepository playerRepository;
public PlayerRepositoryDB (IPlayerRepository playerRepository){ //CONSTRUCTOR
this.playerRepository = playerRepository;...
3- DB repository classes are implementing IPlayerRepository but it must be marked as #Repository and It should extend either CrudRepository or JpaRepository (which extends CrudRepository already).
Like:
#Repository
public interface IPlayerRepository extends JpaRepository<Player, Long> {
//Here are the methods;
}
Here, the Long is the type of primary key of Player class.
Hibernate XML:
<property name="hibernate.connection.CharSet">utf8mb4</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property>
<property name="hibernate.connection.useUnicode">true</property>
Connection url:
db.url=jdbc:mysql://localhost:3306/db_name?useUnicode=true&character_set_server=utf8mb4
As a side note I would like to make one clarification that UTF-8 is the character encoding while utf8mb4 is a character set that MySQL supports. MySQL's utf8mb4 is a superset to MySQL's utf8.
Spring/Hibernate filter:
<form accept-charset="UTF-8">
Problem solved.
It was because of javax.persistence.; import instead of
jakarta.persistence. in entity class.
Related
I am creating a website using Spring MVC and for persistence I am using Spring Data JPA with Hibernate 4 as my JPA provider. Validation is being handled at present with Hibernate Validator. I have a problem whereby my validators are being called twice and I can't figure out why. The main reason this is a problem is because the second time round, dependencies are not being autowired into the validator and I am getting a null pointer exception.
The following is the sequence of calls leading up to the failure:
The registration form is submitted and first the NotDefaultSectValidator is called and completes successfully for the 'whereDidYouHearAboutUs' field on the user object.
The UniqueUsernameValidator is called next and completes successfully for the 'username' field validation.
The 'addUserFromForm' method on the controller starts and finds no errors in the bindingResults object.
The 'addUser' method is then called on the UserService class. This method reaches the line 'userRepository.save(user);' but never then runs the 'print.ln' line immediate afterwards. Stepping over this line takes be back to the 'NotDefaultSectValidator' breakpoint. This completes for the second time and I re-enter the second validator 'UniqueUsernameValidator '. Here I get a null pointer exception because for some reason Spring fails to Autowire in the DAO this second time.
Can anyone shed light on why the validators are being called twice and in particular, why stepping over line 'userRepository.save(user);' goes back into these validators?
Many thanks
Here is my user.java class
package com.dating.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.joda.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
import com.dating.annotation.NotDefaultSelect;
import com.dating.annotation.UniqueUsername;
#Entity
#Table(name = "dating.user")
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "username", unique = true)
#NotEmpty
#Pattern(regexp = "^[a-zA-Z0-9]*$")
#UniqueUsername
private String username;
#Column(name = "password", nullable = false)
#NotEmpty
#Size(min = 8)
private String password;
#Column(name = "first_name", nullable = false)
#NotEmpty
private String firstName;
#Column(name = "last_name", nullable = false)
#NotEmpty
private String lastName;
#Transient
private String fullName;
#Column(name = "email", nullable = false)
#NotEmpty
#Email
private String email;
#Column(name = "gender", nullable = false)
#NotEmpty
private String gender;
#Column(name = "date_of_birth", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
#DateTimeFormat(pattern = "dd/MM/yyyy")
private LocalDate dateOfBirth;
#Column(name = "join_date", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate joinDate;
#Column(name = "where_did_you_hear_about_us", nullable = false)
#NotDefaultSelect
private String whereDidYouHearAboutUs;
#Column(name = "enabled")
private boolean enabled;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "dating.user_roles", joinColumns = { #JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "role_id", nullable = false, updatable = false) })
private Set<Role> roles = new HashSet<Role>();
#Column(name = "created_time", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate createdTime;
#Column(name = "modification_time", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate modificationTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public LocalDate getJoinDate() {
return joinDate;
}
public void setJoinDate(LocalDate joinDate) {
this.joinDate = joinDate;
}
public String getWhereDidYouHearAboutUs() {
return whereDidYouHearAboutUs;
}
public void setWhereDidYouHearAboutUs(String whereDidYouHearAboutUs) {
this.whereDidYouHearAboutUs = whereDidYouHearAboutUs;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void addRole(Role role) {
roles.add(role);
}
public LocalDate getCreatedTime() {
return createdTime;
}
public void setCreatedTime(LocalDate createdTime) {
this.createdTime = createdTime;
}
public LocalDate getModificationTime() {
return modificationTime;
}
public void setModificationTime(LocalDate modificationTime) {
this.modificationTime = modificationTime;
}
#PreUpdate
public void preUpdate() {
modificationTime = new LocalDate();
}
#PrePersist
public void prePersist() {
LocalDate now = new LocalDate();
createdTime = now;
modificationTime = now;
}
}
The relevant method in my registration controller:
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String addUserFromForm(#Valid User user,
BindingResult bindingResult, RedirectAttributes ra) {
if (bindingResult.hasErrors()) {
return "user/register";
}
userService.addUser(user);
// Redirecting to avoid duplicate submission of the form
return "redirect:/user/" + user.getUsername();
}
My service class:
package com.dating.service.impl;
import javax.transaction.Transactional;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.dating.domain.Role;
import com.dating.domain.User;
import com.dating.repository.RoleRepository;
import com.dating.repository.UserRepository;
import com.dating.repository.specification.UserSpecifications;
import com.dating.service.UserService;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Transactional
#Override
public void addUser(User user) {
user.setJoinDate(new LocalDate());
user.setEnabled(true);
Role role = roleRepository.findByName(Role.MEMBER);
if (role == null) {
role = new Role();
role.setName(Role.MEMBER);
}
user.addRole(role);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
userRepository.save(user);
System.out.println("User Saved");
}
#Override
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
#Override
public Iterable<User> getAllUsers() {
return userRepository.findAll();
}
#Override
public void updateDetails(User user) {
userRepository.save(user);
}
#Override
public Iterable<User> lastNameIsLike(String searchTerm) {
return userRepository.findAll(UserSpecifications
.lastNameIsLike(searchTerm));
}
}
My NotDefaultSelect validator:
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.dating.annotation.NotDefaultSelect;
public class NotDefaultSelectValidator implements
ConstraintValidator<NotDefaultSelect, String> {
#Override
public void initialize(NotDefaultSelect constraint) {
}
#Override
public boolean isValid(String selectedValue, ConstraintValidatorContext ctx) {
if (selectedValue == null) {
return false;
}
if (selectedValue.equals("") || selectedValue.equals("0")
|| selectedValue.equalsIgnoreCase("default")
|| selectedValue.equalsIgnoreCase("please select")) {
return false;
}
return true;
}
}
My uniqueUsername validator:
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.dating.annotation.UniqueUsername;
import com.dating.repository.UserRepository;
public class UniqueUsernameValidator implements
ConstraintValidator<UniqueUsername, String> {
#Autowired
private UserRepository userRepository;
#Override
public void initialize(UniqueUsername constraint) {
}
#Override
public boolean isValid(String username, ConstraintValidatorContext ctx) {
if (username == null || userRepository.findByUsername(username) == null) {
return true;
}
return false;
}
}
My UserRepository:
package com.dating.repository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import com.dating.domain.User;
//Spring Data JPA Marker interfaces being extended for automatic CRUD repository creation
public interface UserRepository extends CrudRepository<User, Long>, JpaSpecificationExecutor<User> {
//Automatic query creation from method name
public User findByUsername(String username);
}
Lastly my persistence-context.xml file
<!-- Data source properties -->
<util:properties id="dataSourceSettings" location="classpath:datasource.properties" />
<!-- Pooled data source using BoneCP -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<property name="driverClass" value="#{dataSourceSettings['jdbc.driverClass']}" />
<property name="jdbcUrl" value="#{dataSourceSettings['jdbc.url']}" />
<property name="username" value="#{dataSourceSettings['jdbc.username']}" />
<property name="password" value="#{dataSourceSettings['jdbc.password']}" />
<property name="idleConnectionTestPeriodInMinutes" value="60" />
<property name="idleMaxAgeInMinutes" value="240" />
<property name="maxConnectionsPerPartition" value="30" />
<property name="minConnectionsPerPartition" value="10" />
<property name="partitionCount" value="3" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<property name="releaseHelperThreads" value="3" />
</bean>
<!-- JPA entity manager factory bean -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.dating.domain" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{dataSourceSettings['hibernate.dialect']}</prop>
<prop key="hibernate.hbm2ddl.auto">#{dataSourceSettings['hibernate.hbm2ddl.auto']}
</prop>
<prop key="hibernate.show_sql">#{dataSourceSettings['hibernate.show_sql']}</prop>
<prop key="hibernate.format_sql">#{dataSourceSettings['hibernate.format_sql']}</prop>
<prop key="hibernate.use_sql_comments">#{dataSourceSettings['hibernate.use_sql_comments']}
</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:annotation-config />
<jpa:repositories base-package="com.dating.repository"/>
Maybe the second validation is done by hibernate when you are sending your bean to the datastore. To turn it off add this to your persistence.xml:
<property name="javax.persistence.validation.mode" value="none"/>
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html says:
By default, Bean Validation (and Hibernate Validator) is activated. When an entity is created, updated (and optionally deleted), it is validated before being sent to the database. The database schema generated by Hibernate also reflects the constraints declared on the entity.
You can fine-tune that if needed:
AUTO: if Bean Validation is present in the classpath, CALLBACK and DDL are activated.
CALLBACK: entities are validated on creation, update and deletion. If no Bean Validation provider is present, an exception is raised at initialization time.
DDL: (not standard, see below) database schemas are entities are validated on creation, update and deletion. If no Bean Validation provider is present, an exception is raised at initialization time.
NONE: Bean Validation is not used at all
The first one is obviously done by your Spring controller because of #Valid annotation.
You can just add this property in your application.property files to disable hibernate validation spring.jpa.properties.javax.persistence.validation.mode=none
I am new to Hibernate (implementing since yesterday) and i succesfully created a method, that transfers my Customer Objects to the Database.
After i quit my application and start it again and create a new session (in an other method) based on my hibernate.cfg.xml file with this setting:
<property name="hibernate.hbm2ddl.auto">create</property>
It leads to that point, that all relevant tables, created with Hibernate are being deleted.
So maybe that is a comprehension question, but i think "transparent persistence by hibernate" means also, that my POJO's are persistent beyond the runtime of my application!?
So i read several topics on Stackoverflow and tried it with this setting:
<property name="hibernate.hbm2ddl.auto">update</property>
But this leads to SQL errors:
com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
Of course i don't want have duplicates, so i suppose that hibernate doesn't send a SQL Statement referring to an existing object.
It sends a Statement like this:
UPDATE `customer` SET `id`=1,`birthday`='1990-10-05 00:00:00',`forename`='TestCustomer',`gender`='F',`generatedProfitsLastYear`='0',`generatedProfitsTotal`='0',`surename`='A',`gcid`='1'
But i need the same statement, with a
Where `id`=1
at the end.
So basically what i want is, that hibernate doesn't drop all the tables and creates it again when i restart my application and create a new session based on the configuration file. So after i open a new session, i can transfer the Customer Objects stored in the database to POJOs.
Did i understand the concept of hibernate incorrectly or am i making a typical beginners mistake?
Below you will find my Customer Class:
#Entity
#Table(name="CUSTOMER")
public class Customer {
private int id;
private String forename;
private String surname;
private char gender;
private Date birthday;
private double generatedProfitsTotal;
private double generatedProfitsLastYear;
private CustomerGroup assignedTo;
public Customer(int id, String forename, String surname, char gender,
Date birthday) {
super();
this.id = id;
this.forename = forename;
this.surname = surname;
this.gender = gender;
this.birthday = birthday;
}
#Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "forename")
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
#Column(name = "surename")
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Column(name = "gender")
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
#Column(name = "birthday")
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
#Column(name = "generatedProfitsTotal")
public double getGeneratedProfitsTotal() {
return generatedProfitsTotal;
}
public void setGeneratedProfitsTotal(double generatedProfitsTotal) {
this.generatedProfitsTotal = generatedProfitsTotal;
}
#Column(name = "generatedProfitsLastYear")
public double getGeneratedProfitsLastYear() {
return generatedProfitsLastYear;
}
public void setGeneratedProfitsLastYear(double generatedProfitsLastYear) {
this.generatedProfitsLastYear = generatedProfitsLastYear;
}
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="gcid", nullable=true, insertable=true, updatable=true)
public CustomerGroup getAssignedTo() {
return assignedTo;
}
public void setAssignedTo(CustomerGroup assignedTo) {
this.assignedTo = assignedTo;
}
}
my hibernate config file:
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1/hibernatetesting</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="studyproject.Customer"/>
<mapping class="studyproject.CustomerGroup"/>
<mapping class="studyproject.BonusPackage"/>
</session-factory>
</hibernate-configuration>
Thanks
try session.saveOrUpdate() method where you have used session.save() it will prevent your database from dropping while fetching data use it with hbm2ddl.auto update. it worked for me. hope it helps.
What did you do where the 'duplicate error' occurs? Now I have the hibernate.hbm2ddl.auto configured as yours, but it's okay saving or updating entity in my local.
I've got a problem. I spend over one hour searching through the Internet but I did find nothing....
I have a simple Table class and one of its elements is List of java.util.Date. When I run the program, the exception is shown:
> org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany
> targeting an unmapped class:
> com.model.Time.timetable[java.util.Date].
My config file:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume test is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3036/test
</property>
<property name="hibernate.connection.username">
root
</property>
<property name="hbm2ddl.auto">create</property>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<mapping class="com.model.Cinema" />
<mapping class="com.model.Time" />
</session-factory>
</hibernate-configuration>
and my class:
package com.model;
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import info.talacha.filmweb.models.Movie;
#Entity
#Table(name = "Time")
public class Time implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private int id;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "time_id")
private List<Date> timetable;
#Column(name = "movie")
private Movie movie;
#Column(name = "dubbing")
private boolean dubbing;
#Column(name = "subtitles")
private boolean subtitles;
#Column(name = "threeDimensions")
private boolean threeDimensions;
public Time(){
timetable = new ArrayList<Date>();
dubbing= false;
subtitles = false;
threeDimensions = false;
movie = new Movie();
}
public Time(int id, List<Date> timetable, Movie movie, boolean dubbing, boolean subtitles, boolean is3dMovie) {
super();
this.id = id;
this.timetable = timetable;
this.movie = movie;
this.dubbing = dubbing;
this.subtitles = subtitles;
threeDimensions = is3dMovie;
}
public boolean isThreeDimensions() {
return threeDimensions;
}
public void setThreeDimensions(boolean threeDimensions) {
this.threeDimensions = threeDimensions;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
public Time(List<Date> timetable, Movie movie,boolean dubbing, boolean subtitles,boolean is3D) {
this.timetable = timetable;
this.dubbing = dubbing;
this.subtitles = subtitles;
this.movie = movie;
this.threeDimensions = is3D;
}
public List<Date> getTimetable() {
return timetable;
}
public void setTimetable(List<Date> timetable) {
this.timetable = timetable;
}
public boolean isDubbing() {
return dubbing;
}
public void setDubbing(boolean dubbing) {
this.dubbing = dubbing;
}
public boolean isSubtitles() {
return subtitles;
}
public void setSubtitles(boolean subtitles) {
this.subtitles = subtitles;
}
#Override
public String toString() {
return "Time [timetable=" + timetable + ", movie=" + movie + ", dubbing=" + dubbing + ", subtitles="
+ subtitles + ", is3DMovie=" + threeDimensions + "]";
}
}
This way of mapping (oneToMany) worked great when I used it for different type... I have no idea what's wrong. I tried few things but they didn't work. I will be grateful for your help!
OneToMany is used to create an association between two entities. java.util.Date is not an entity. It's a basic type. What you want is #ElementCollection.
Try usin #Temporal annotation like this:
#Temporal(value = TemporalType.TIMESTAMP)
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "time_id")
private List<Date> timetable;
Try Date attribut from java.sql.Date to define each Date attributs of the Time class.
See you.
Hi I am doing project in Spring Roo. Where can I put restrictions that the phone number must be 10 digits? I have already put restrictions in create.jspx and in User_Roo_DbManaged.aj but it doesn't work.
it accepts letters and shorter input.
create.jspx
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/jquery/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/jquery/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<form:create id="fc_edu_ndnu_capstone_domain_User" modelAttribute="user" path="/users" render="${empty dependencies}" z="wGrfaSchPJDWXlsq1jiCSRc0pAA=">
<field:simple field="emergencies" id="c_edu_ndnu_capstone_domain_User_emergencies" messageCode="entity_reference_not_managed" messageCodeAttribute="Emergency" z="96v/orisk+QZ0UvamFbdCmNUM9g="/>
<field:select field="typeId" id="c_edu_ndnu_capstone_domain_User_typeId" itemValue="id" items="${usertypes}" path="/usertypes" z="cuXEuKQFS8VdksWWbETwOj+Ps4k="/>
<field:input field="name" id="c_edu_ndnu_capstone_domain_User_name" required="true" z="AvB38b/End0hXemXNC8GrbD8SAw="/>
<field:input field="email" id="c_edu_ndnu_capstone_domain_User_email" required="true" validationMessageCode="field_invalid_email" z="OGADRfESfWyp/4F216swLnNdyoQ="/>
<field:input field="username" id="c_edu_ndnu_capstone_domain_User_username" required="true" z="MiEOzhgH466ktY7pKT/tYMLt5S0="/>
<field:input field="password" id="c_edu_ndnu_capstone_domain_User_password" required="true" z="kEW4oQdeXWi+JyIwdUJkmMKHYII=" type="password"/>
<field:input field="phone" id="c_edu_ndnu_capstone_domain_User_phone" required="true" validationMessageCode="field_invalid_number" max="10" min="10" z="k42Av41wIfhbInJmZhCY/WbW+h4="/>
<field:input field="year" id="c_edu_ndnu_capstone_domain_User_year" required="true" validationMessageCode="field_invalid_number" max="4" min="4" z="HL+hSR+nz8/34t6nn2HXLRJaIyA="/>
<field:input field="active" id="c_edu_ndnu_capstone_domain_User_active" required="true" validationMessageCode="field_invalid_integer" max="1" min="1" z="wMEcOQjcrIJKY5RQ7mQ4/Uu9Ago="/>
<field:input field="description" id="c_edu_ndnu_capstone_domain_User_description" required="true" z="6TJHmWCAvkCtONvKOBHftLCMtso="/>
</form:create>
<form:dependency dependencies="${dependencies}" id="d_edu_ndnu_capstone_domain_User" render="${not empty dependencies}" z="Do0kIZAQM8ZWzWNlt1c/uMANnj4="/>
</div>
User_Roo_DbManaged.aj
// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).
package edu.ndnu.capstone.domain;
import edu.ndnu.capstone.domain.Emergency;
import edu.ndnu.capstone.domain.User;
import edu.ndnu.capstone.domain.UserType;
import java.util.Calendar;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import org.springframework.format.annotation.DateTimeFormat;
privileged aspect User_Roo_DbManaged {
#OneToMany(mappedBy = "userId")
private Set<Emergency> User.emergencies;
#ManyToOne
#JoinColumn(name = "type_id", referencedColumnName = "id", nullable = false)
private UserType User.typeId;
#Column(name = "name", length = 256)
#NotNull
private String User.name;
#Column(name = "email", length = 256, unique = true)
#NotNull
private String User.email;
#Column(name = "username", length = 150, unique = true)
#NotNull
private String User.username;
#Column(name = "password")
#NotNull
private String User.password;
#Column(name = "phone", length = 10, unique = true)
#NotNull
private String User.phone;
#Column(name = "year", length = 4)
#NotNull
private String User.year;
#Column(name = "active", length = 1)
#NotNull
private Integer User.active;
#Column(name = "created", updatable = false)
#NotNull
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(style = "MM")
private Calendar User.created = java.util.Calendar.getInstance();
#Column(name = "description", length = 1024)
#NotNull
private String User.description;
public Set<Emergency> User.getEmergencies() {
return emergencies;
}
public void User.setEmergencies(Set<Emergency> emergencies) {
this.emergencies = emergencies;
}
public UserType User.getTypeId() {
return typeId;
}
public void User.setTypeId(UserType typeId) {
this.typeId = typeId;
}
public String User.getName() {
return name;
}
public void User.setName(String name) {
this.name = name;
}
public String User.getEmail() {
return email;
}
public void User.setEmail(String email) {
this.email = email;
}
public String User.getUsername() {
return username;
}
public void User.setUsername(String username) {
this.username = username;
}
public String User.getPassword() {
return password;
}
public void User.setPassword(String password) {
this.password = password;
}
public String User.getPhone() {
return phone;
}
public void User.setPhone(String phone) {
this.phone = phone;
}
public String User.getYear() {
return year;
}
public void User.setYear(String year) {
this.year = year;
}
public Integer User.getActive() {
return active;
}
public void User.setActive(Integer active) {
if(active==0 || active==1)
this.active = active;
else
this.active = 2;
}
public Calendar User.getCreated() {
return created;
}
public void User.setCreated(Calendar created) {
this.created = created;
}
public String User.getDescription() {
return description;
}
public void User.setDescription(String description) {
this.description = description;
}
}
First, you shouldn't modify any .aj because Spring Roo will overwrite your changes next time you run it. To customize your field you have to move its declaration into related .java file (we call it push-in).
To set the field validation, Roo uses the JSR-303 specification, using the Hibernate validation as implementation.
So, to archive it, try:
Push-in the phone declaration into User.java and add javax.validation.constraints.Size annotation:
public class User {
#Column(name = "phone", length = 10, unique = true)
#NotNull
#Size(max=10,min=10)
private String phone;
}
Run Spring Roo console.
After that, Roo will:
remove phone definition from User_Roo_DbManaged.aj
create the getter and setter on User_Roo_bean.aj
Update User related .jspx
Note that #Column definition refers to database declaration. Any other field validation you should use the javax.validation.constraints.* annotations or create yours (here you have an example)
Good luck!
I am creating a website using Spring MVC and for persistence I am using Spring Data JPA with Hibernate 4 as my JPA provider. Validation is being handled at present with Hibernate Validator. I have a problem whereby my validators are being called twice and I can't figure out why. The main reason this is a problem is because the second time round, dependencies are not being autowired into the validator and I am getting a null pointer exception.
The following is the sequence of calls leading up to the failure:
The registration form is submitted and first the NotDefaultSectValidator is called and completes successfully for the 'whereDidYouHearAboutUs' field on the user object.
The UniqueUsernameValidator is called next and completes successfully for the 'username' field validation.
The 'addUserFromForm' method on the controller starts and finds no errors in the bindingResults object.
The 'addUser' method is then called on the UserService class. This method reaches the line 'userRepository.save(user);' but never then runs the 'print.ln' line immediate afterwards. Stepping over this line takes be back to the 'NotDefaultSectValidator' breakpoint. This completes for the second time and I re-enter the second validator 'UniqueUsernameValidator '. Here I get a null pointer exception because for some reason Spring fails to Autowire in the DAO this second time.
Can anyone shed light on why the validators are being called twice and in particular, why stepping over line 'userRepository.save(user);' goes back into these validators?
Many thanks
Here is my user.java class
package com.dating.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.joda.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
import com.dating.annotation.NotDefaultSelect;
import com.dating.annotation.UniqueUsername;
#Entity
#Table(name = "dating.user")
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "username", unique = true)
#NotEmpty
#Pattern(regexp = "^[a-zA-Z0-9]*$")
#UniqueUsername
private String username;
#Column(name = "password", nullable = false)
#NotEmpty
#Size(min = 8)
private String password;
#Column(name = "first_name", nullable = false)
#NotEmpty
private String firstName;
#Column(name = "last_name", nullable = false)
#NotEmpty
private String lastName;
#Transient
private String fullName;
#Column(name = "email", nullable = false)
#NotEmpty
#Email
private String email;
#Column(name = "gender", nullable = false)
#NotEmpty
private String gender;
#Column(name = "date_of_birth", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
#DateTimeFormat(pattern = "dd/MM/yyyy")
private LocalDate dateOfBirth;
#Column(name = "join_date", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate joinDate;
#Column(name = "where_did_you_hear_about_us", nullable = false)
#NotDefaultSelect
private String whereDidYouHearAboutUs;
#Column(name = "enabled")
private boolean enabled;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "dating.user_roles", joinColumns = { #JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "role_id", nullable = false, updatable = false) })
private Set<Role> roles = new HashSet<Role>();
#Column(name = "created_time", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate createdTime;
#Column(name = "modification_time", nullable = false)
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate modificationTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public LocalDate getJoinDate() {
return joinDate;
}
public void setJoinDate(LocalDate joinDate) {
this.joinDate = joinDate;
}
public String getWhereDidYouHearAboutUs() {
return whereDidYouHearAboutUs;
}
public void setWhereDidYouHearAboutUs(String whereDidYouHearAboutUs) {
this.whereDidYouHearAboutUs = whereDidYouHearAboutUs;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void addRole(Role role) {
roles.add(role);
}
public LocalDate getCreatedTime() {
return createdTime;
}
public void setCreatedTime(LocalDate createdTime) {
this.createdTime = createdTime;
}
public LocalDate getModificationTime() {
return modificationTime;
}
public void setModificationTime(LocalDate modificationTime) {
this.modificationTime = modificationTime;
}
#PreUpdate
public void preUpdate() {
modificationTime = new LocalDate();
}
#PrePersist
public void prePersist() {
LocalDate now = new LocalDate();
createdTime = now;
modificationTime = now;
}
}
The relevant method in my registration controller:
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String addUserFromForm(#Valid User user,
BindingResult bindingResult, RedirectAttributes ra) {
if (bindingResult.hasErrors()) {
return "user/register";
}
userService.addUser(user);
// Redirecting to avoid duplicate submission of the form
return "redirect:/user/" + user.getUsername();
}
My service class:
package com.dating.service.impl;
import javax.transaction.Transactional;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.dating.domain.Role;
import com.dating.domain.User;
import com.dating.repository.RoleRepository;
import com.dating.repository.UserRepository;
import com.dating.repository.specification.UserSpecifications;
import com.dating.service.UserService;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Transactional
#Override
public void addUser(User user) {
user.setJoinDate(new LocalDate());
user.setEnabled(true);
Role role = roleRepository.findByName(Role.MEMBER);
if (role == null) {
role = new Role();
role.setName(Role.MEMBER);
}
user.addRole(role);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
userRepository.save(user);
System.out.println("User Saved");
}
#Override
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
#Override
public Iterable<User> getAllUsers() {
return userRepository.findAll();
}
#Override
public void updateDetails(User user) {
userRepository.save(user);
}
#Override
public Iterable<User> lastNameIsLike(String searchTerm) {
return userRepository.findAll(UserSpecifications
.lastNameIsLike(searchTerm));
}
}
My NotDefaultSelect validator:
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.dating.annotation.NotDefaultSelect;
public class NotDefaultSelectValidator implements
ConstraintValidator<NotDefaultSelect, String> {
#Override
public void initialize(NotDefaultSelect constraint) {
}
#Override
public boolean isValid(String selectedValue, ConstraintValidatorContext ctx) {
if (selectedValue == null) {
return false;
}
if (selectedValue.equals("") || selectedValue.equals("0")
|| selectedValue.equalsIgnoreCase("default")
|| selectedValue.equalsIgnoreCase("please select")) {
return false;
}
return true;
}
}
My uniqueUsername validator:
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.dating.annotation.UniqueUsername;
import com.dating.repository.UserRepository;
public class UniqueUsernameValidator implements
ConstraintValidator<UniqueUsername, String> {
#Autowired
private UserRepository userRepository;
#Override
public void initialize(UniqueUsername constraint) {
}
#Override
public boolean isValid(String username, ConstraintValidatorContext ctx) {
if (username == null || userRepository.findByUsername(username) == null) {
return true;
}
return false;
}
}
My UserRepository:
package com.dating.repository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import com.dating.domain.User;
//Spring Data JPA Marker interfaces being extended for automatic CRUD repository creation
public interface UserRepository extends CrudRepository<User, Long>, JpaSpecificationExecutor<User> {
//Automatic query creation from method name
public User findByUsername(String username);
}
Lastly my persistence-context.xml file
<!-- Data source properties -->
<util:properties id="dataSourceSettings" location="classpath:datasource.properties" />
<!-- Pooled data source using BoneCP -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<property name="driverClass" value="#{dataSourceSettings['jdbc.driverClass']}" />
<property name="jdbcUrl" value="#{dataSourceSettings['jdbc.url']}" />
<property name="username" value="#{dataSourceSettings['jdbc.username']}" />
<property name="password" value="#{dataSourceSettings['jdbc.password']}" />
<property name="idleConnectionTestPeriodInMinutes" value="60" />
<property name="idleMaxAgeInMinutes" value="240" />
<property name="maxConnectionsPerPartition" value="30" />
<property name="minConnectionsPerPartition" value="10" />
<property name="partitionCount" value="3" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<property name="releaseHelperThreads" value="3" />
</bean>
<!-- JPA entity manager factory bean -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.dating.domain" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{dataSourceSettings['hibernate.dialect']}</prop>
<prop key="hibernate.hbm2ddl.auto">#{dataSourceSettings['hibernate.hbm2ddl.auto']}
</prop>
<prop key="hibernate.show_sql">#{dataSourceSettings['hibernate.show_sql']}</prop>
<prop key="hibernate.format_sql">#{dataSourceSettings['hibernate.format_sql']}</prop>
<prop key="hibernate.use_sql_comments">#{dataSourceSettings['hibernate.use_sql_comments']}
</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:annotation-config />
<jpa:repositories base-package="com.dating.repository"/>
Maybe the second validation is done by hibernate when you are sending your bean to the datastore. To turn it off add this to your persistence.xml:
<property name="javax.persistence.validation.mode" value="none"/>
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html says:
By default, Bean Validation (and Hibernate Validator) is activated. When an entity is created, updated (and optionally deleted), it is validated before being sent to the database. The database schema generated by Hibernate also reflects the constraints declared on the entity.
You can fine-tune that if needed:
AUTO: if Bean Validation is present in the classpath, CALLBACK and DDL are activated.
CALLBACK: entities are validated on creation, update and deletion. If no Bean Validation provider is present, an exception is raised at initialization time.
DDL: (not standard, see below) database schemas are entities are validated on creation, update and deletion. If no Bean Validation provider is present, an exception is raised at initialization time.
NONE: Bean Validation is not used at all
The first one is obviously done by your Spring controller because of #Valid annotation.
You can just add this property in your application.property files to disable hibernate validation spring.jpa.properties.javax.persistence.validation.mode=none