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
Related
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.
Hi I am currently learning Hibernate and I am stuck on a problem where I am trying to override the column name from address to home address and office address. I commented out all office-address code, but the column in database are still "CITY_NAME", "STREET_NAME" and etc.
Could someone please explain this, thanks.
Address.java
package org.zm.javabrain.dto;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class Address {
#Column(name="STREET_NAME")
private String stree;
#Column(name="CITY_NAME")
private String city;
#Column(name="STATE_NAME")
private String state;
#Column(name="ZIP_NAME")
private String zip;
public String getStree() {
return stree;
}
public void setStree(String stree) {
this.stree = stree;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
this is UserDetails.java
package org.zm.javabrain.dto;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
#Entity // change the name of the entity
#Table(name="USER_DETAILS") // change the name of the table
public class UserDetails implements Serializable {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
private String username;
private Date joinedDate;
private String description;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="street",column=#Column(name="HOME_STREET_NAME")),
#AttributeOverride(name="city",column=#Column(name="HOME_CITY_NAME")),
#AttributeOverride(name="state",column=#Column(name="HOME_STATE_NAME")),
#AttributeOverride(name="zip",column=#Column(name="HOME_ZIP_NAME"))})
private Address homeAddress;
// #Embedded
// #AttributeOverrides({
// #AttributeOverride(name="street",column=#Column(name="OFFICE_STREET_NAME")),
// #AttributeOverride(name="city",column=#Column(name="OFFICE_CITY_NAME")),
// #AttributeOverride(name="state",column=#Column(name="OFFICE_STATE_NAME")),
// #AttributeOverride(name="zip",column=#Column(name="OFFICE_ZIP_NAME"))})
// private Address officeAddress;
//
// public Address getOfficeAddress() {
// return officeAddress;
// }
// public void setOfficeAddress(Address officeAddress) {
// this.officeAddress = officeAddress;
// }
public Date getJoinedDate() {
return joinedDate;
}
public void setJoinedDate(Date joinedDate) {
this.joinedDate = joinedDate;
}
public Address getHomeAddress() {
return homeAddress;
}
public void setHomeAddress(Address homeAddress) {
this.homeAddress = homeAddress;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
This is driver class
package org.zm.hibernate;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.zm.javabrain.dto.Address;
import org.zm.javabrain.dto.UserDetails;
public class HibernateTest {
public static void main(String[] args) {
UserDetails user = new UserDetails();
Address addr = new Address();
addr.setCity("chicago");
addr.setState("IL");
addr.setStree("Michigen Ave");
addr.setZip("55414");
Address officeAddr = new Address();
officeAddr.setCity("minneapolis");
officeAddr.setState("Washington Ave");
officeAddr.setState("MN");
officeAddr.setZip("55455");
user.setUsername("11111");
user.setHomeAddress(addr);
// user.setOfficeAddress(officeAddr);
user.setJoinedDate(new Date());
user.setDescription("this is a description");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
}
I cannot tell you if Hibernate Session supports the AttributeOverride feature or not. The problem is, I guess, Hibernate is mixing two different technologies that are trying to solve the same problem, and that is confusing for new users trying to learn. Hibernate can be used as
Legacy (Native) ORM , and
JPA (Java Persistence API) implementation
As I can see from your posted code example that you are using JPA annotations. All annotations, classes and properties having the package structure of javax.persistence are JPA specific. So my advice is, either configure your persistence the Hibernate way or the JPA way, and don't mix.
If you want to map your entities the JPA way, do the following:
Put your configuration information in the file persistence.xml instead of in the hibernate.cfg.xml. The file should be under META-INF folder of your source directory. If you are using Maven put it under src/main/resources/META-INF directory. The file should look like:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="yourPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>org.zm.javabrain.dto.UserDetails</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="..." />
<property name="javax.persistence.jdbc.url" value="..." />
<property name="javax.persistence.jdbc.user" value="..." />
<property name="javax.persistence.jdbc.password" value="..." />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
replace the ... with correct database information.
In your test class (HibernateTest) do the following instead of SessionFactory / Session:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("yourPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit;
em.close();
emf.close();
You can also read:
Hibernate User Guide
Java Persistence API Tutorials
JPA 2.1 Specification
Hopefully, it helps.
I am writing a Java project that uses Hibernate ORM and Spring Framework. Right now, when I add a POJO class, I need to modify my hibernate.cfg.xml file, which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="somepackage.class1"/>
<mapping class="somepackage.class2"/>
<!-- etc. -->
</session-factory>
</hibernate-configuration>
Then, I create an annotation-based class. I heard that I could avoid adding per-class mappings in hibernate.cfg.xml if I used proper Hibernate annotations. How can I modify a class to avoid the mappings in an XML file? Here is my example POJO file, generated by NetBeans:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package somepackage.pojo;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* #author D
*/
#Entity
#Table(name = "ACCOUNT")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Account.findAll", query = "SELECT a FROM Account a"),
#NamedQuery(name = "Account.findByLogin", query = "SELECT a FROM Account a WHERE a.login = :login"),
#NamedQuery(name = "Account.findByPassword", query = "SELECT a FROM Account a WHERE a.password = :password")})
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(name = "LOGIN", nullable = false, length = 100)
private String login;
#Size(max = 128)
#Column(name = "PASSWORD", length = 128)
private String password;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "author")
private Collection<Comment> commentCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "author")
private Collection<Article> articleCollection;
public Account() {
}
public Account(String login) {
this.login = login;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#XmlTransient
public Collection<Comment> getCommentCollection() {
return commentCollection;
}
public void setCommentCollection(Collection<Comment> commentCollection) {
this.commentCollection = commentCollection;
}
#XmlTransient
public Collection<Article> getArticleCollection() {
return articleCollection;
}
public void setArticleCollection(Collection<Article> articleCollection) {
this.articleCollection = articleCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (login != null ? login.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Account)) {
return false;
}
Account other = (Account) object;
if ((this.login == null && other.login != null) || (this.login != null && !this.login.equals(other.login))) {
return false;
}
return true;
}
#Override
public String toString() {
return "somepackage.pojo.Account[ login=" + login + " ]";
}
}
I'd suggest you export the hibernate configuration to the spring configuration because of the flexibility that spring provides. Your concern is to not declare the class in the configuration every time you create a new entity. Using spring configuration you can do the following. (packagestoscan property)
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.baeldung.spring.persistence.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
Ref: http://www.javacodegeeks.com/2013/05/hibernate-3-with-spring.html
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 have 2 entities User and Status. I can load users list and can see its sql(log) in console
(select this_.id as id0_0_,
this_.cl_point_id as cl2_0_0_,
this_.date_ll as date3_0_0_,
this_.date_reg as date4_0_0_,
this_.name as name0_0_,
this_.passw_salt as passw6_0_0_,
this_.status_id as status7_0_0_,
this_.passw as passw0_0_, this_.login
as login0_0_ from users this_)
.
But when I load Status the list is empty and there is no sql(log) in console. I can't find where is the problem?
User.java
package tj.eskhata.pos.domain;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.*;
#Entity
#Table(name="users")
public class User implements DomainObject {
#Id
private Long id;
#Column(name="name")
private String fullname;
#Column(name="cl_point_id")
private Long clPointId;
#Column(name="login")
private String wiaUsername;
#Column(name="passw")
private String wiaPassword;
#Column(name="status_id")
private Long statusId;
#Column(name="date_reg")
private Date dateReg;
#Column(name="date_ll")
private Date dateLl;
#Column(name="passw_salt")
private String passwSalt;
public User() {
}
public User(String username, String password, String fullname,
boolean isAdmin) {
this.id=Long.valueOf(1);
this.wiaUsername = username;
this.wiaPassword = password;
this.fullname = fullname;
}
public String getFullname() {
return fullname;
}
public String getWiaPassword() {
return wiaPassword;
}
public String getWiaUsername() {
return wiaUsername;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public void setWiaPassword(String password) {
this.wiaPassword = password;
}
public void setWiaUsername(String username) {
this.wiaUsername = username;
}
public Long getId() {
return id;
}
public Long getClPointId() {
return clPointId;
}
public Long getStatusId() {
return statusId;
}
public Date getDateReg() {
return dateReg;
}
public Date getDateLl() {
return dateReg;
}
public String getPasswSalt() {
return passwSalt;
}
public void getClPointId(Long clPointId_) {
this.clPointId=clPointId_;
}
public void setStatusId(Long statusId_) {
this.statusId=statusId_;
}
public void setDateReg(Date dateReg_) {
this.dateReg=dateReg_;
}
public void setDateLl(Date dateLl_) {
this.dateLl=dateLl_;
}
public void setPasswSalt(String passwSalt_) {
this.passwSalt=passwSalt_;
}
public boolean isAdmin() {
return false;
}
}
Status.java
package tj.eskhata.pos.domain;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.*;
#Entity
#Table(name="status")
public class Status implements DomainObject {
public Status() {
}
public Status(Long id) {
this.id = id;
}
public Status(Long id, String code, String name, String fullName,
String color) {
this.id = id;
this.code = code;
this.name = name;
this.fullName = fullName;
this.color = color;
}
#Id
private Long id;
public void setId( Long id_) {
this.id=id_;
}
public Long getId() {
return this.id;
}
#Column(name = "code")
private String code;
public void setCode( String code_) {
this.code=code_;
}
public String getCode() {
return this.code;
}
#Column(name = "name")
private String name;
public void setName( String name_) {
this.name=name_;
}
public String getName() {
return this.name;
}
#Column(name = "full_name")
private String fullName;
public void setFullName( String fullName_) {
this.name=fullName_;
}
public String getFullName() {
return this.fullName;
}
#Column(name = "color")
private String color;
public void setColor( String color_) {
this.color=color_;
}
public String getColor() {
return this.color;
}
}
*
UserDaoImpl.java:
package tj.eskhata.pos.dao.hibernate;
import tj.eskhata.pos.dao.UserDao;
import tj.eskhata.pos.domain.User;
public class UserDaoImpl extends AbstractHibernateDaoImpl<User>
implements UserDao {
public UserDaoImpl() {
super(User.class);
}
}
StatusDaoImpl.java:
package tj.eskhata.pos.dao.hibernate;
import tj.eskhata.pos.dao.StatusDao;
import tj.eskhata.pos.domain.Status;
public class StatusDaoImpl extends AbstractHibernateDaoImpl<Status>
implements StatusDao {
public StatusDaoImpl() {
super(Status.class);
}
}
UserDao.java:
package tj.eskhata.pos.dao;
import tj.eskhata.pos.domain.User;
public interface UserDao extends Dao<User> {
}
StatusDao.java:
package tj.eskhata.pos.dao;
import tj.eskhata.pos.domain.Status;
public interface StatusDao extends Dao<Status> {
}
AbstractHibernateDaoImpl.java:
package tj.eskhata.pos.dao.hibernate;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import tj.eskhata.pos.dao.Dao;
import tj.eskhata.pos.domain.DomainObject;
public abstract class AbstractHibernateDaoImpl<T extends DomainObject>
implements Dao<T> {
private Class<T> domainClass;
private SessionFactory sf;
public AbstractHibernateDaoImpl(Class<T> domainClass) {
this.domainClass = domainClass;
}
public SessionFactory getSessionFactory() {
return sf;
}
public void setSessionFactory(SessionFactory sf) {
this.sf = sf;
}
public void delete(T object) {
getSession().delete(object);
}
#SuppressWarnings("unchecked")
public T load(long id) {
return (T) getSession().get(domainClass, id);
}
public void save(T object) {
getSession().saveOrUpdate(object);
}
#SuppressWarnings("unchecked")
public List<T> findAll() {
Criteria criteria = getSession().createCriteria(domainClass);
List<T> r=(List<T>) criteria.list();
return r;
}
public int countAll() {
Criteria criteria = getSession().createCriteria(domainClass);
criteria.setProjection(Projections.rowCount());
return (Integer) criteria.uniqueResult();
}
public Session getSession() {
// presumes a current session, which we have through the
// OpenSessionInViewFilter; doesn't work without that
return sf.getCurrentSession();
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jndi="http://www.springframework.org/schema/jndi"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jndi
http://www.springframework.org/schema/jndi/spring-jndi.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>${jdbc.driver}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="minPoolSize">
<value>${c3p0.minPoolSize}</value>
</property>
<property name="maxPoolSize">
<value>${c3p0.maxPoolSize}</value>
</property>
<property name="checkoutTimeout">
<value>20000</value>
</property>
<property name="maxIdleTime">
<value>${c3p0.maxIdleTime}</value>
</property>
<property name="idleConnectionTestPeriod">
<value>${c3p0.idleConnectionTestPeriod}</value>
</property>
<property name="automaticTestTable">
<value>${c3p0.automaticTestTable}</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>tj.eskhata.pos.domain.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven />
<bean id="wicketApplication"
class="tj.eskhata.pos.PosApplication">
</bean>
<bean id="UserDao"
class="tj.eskhata.pos.dao.hibernate.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="CountryDao"
class="tj.eskhata.pos.dao.hibernate.CountryDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="StatusDao"
class="tj.eskhata.pos.dao.hibernate.StatusDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="GenericDao"
class="tj.eskhata.pos.dao.hibernate.GenericDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="DiscountsService" class="tj.eskhata.pos.services.DiscountsServiceImpl">
<property name="userDao" ref="UserDao" />
<property name="countryDao" ref="CountryDao" />
<property name="statusDao" ref="StatusDao" />
<property name="genericDao" ref="GenericDao" />
</bean>
</beans>
DiscountService:
package tj.eskhata.pos.services;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import tj.eskhata.pos.domain.Country;
import tj.eskhata.pos.domain.Status;
import tj.eskhata.pos.domain.User;
public interface DiscountsService {
<T> T load(Class<T> type, long id);
List<User> findAllUsers();
void saveUser(User user);
void deleteUser(User user);
List<Country> findAllCountries();
void saveCountry(Country country);
void deleteCountry(Country country);
List<Status> findAllStatuses();
void saveStatus(Status status);
void deleteStatus(Status status);
}
package tj.eskhata.pos.services;
import java.util.List;
import tj.eskhata.pos.dao.CountryDao;
import tj.eskhata.pos.dao.GenericDao;
import tj.eskhata.pos.dao.StatusDao;
import tj.eskhata.pos.dao.UserDao;
import tj.eskhata.pos.domain.Country;
import tj.eskhata.pos.domain.Status;
import tj.eskhata.pos.domain.User;
public class DiscountsServiceImpl implements DiscountsService {
private UserDao userDao;
private CountryDao countryDao;
private StatusDao statusDao;
private GenericDao genericDao;
public DiscountsServiceImpl() {
}
public <T> T load(Class<T> type, long id) {
return genericDao.load(type, id);
}
public List<User> findAllUsers() {
return userDao.findAll();
}
public void saveUser(User user) {
userDao.save(user);
}
public void deleteUser(User user) {
userDao.delete(user);
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public List<Country> findAllCountries() {
return countryDao.findAll();
}
public void saveCountry(Country country) {
countryDao.save(country);
}
public void deleteCountry(Country country) {
countryDao.delete(country);
}
public CountryDao getCountryDao() {
return countryDao;
}
public void setCountryDao(CountryDao countryDao) {
this.countryDao = countryDao;
}
public List<Status> findAllStatuses() {
return statusDao.findAll();
}
public void saveStatus(Status status) {
statusDao.save(status);
}
public void deleteStatus(Status status) {
statusDao.delete(status);
}
public StatusDao getStatusDao() {
return statusDao;
}
public void setStatusDao(StatusDao statusDao) {
this.statusDao = statusDao;
}
public GenericDao getGenericDao() {
return genericDao;
}
public void setGenericDao(GenericDao genericDao) {
this.genericDao = genericDao;
}
}
The Status entity looks fine (it has an #Entity annotation, it has a default no-arg constructor, it has an #Id), I can't spot anything obvious.
So I would:
double check the startup logs to check for any complaint.
use the Hibernate Console (if you are using Eclipse) or any equivalent to load the Status using raw HQL or Criteria.
write a unit test anyway.
Oh, by the way, this is unrelated but you shouldn't have such things in your User entity:
#Column(name="status_id")
private Long statusId;
These Long look like foreign keys. When using an ORM, you should have objects and associations between objects, not ids. Something like this:
#ManyToOne
private Status status;
Same remark for clPointId.
You are IMHO thinking "too relational" and "not enough object". I might be wrong but having foreign key attributes in an entity is a strong hint.
I have changed #Column(name="status_id") private Long statusId; to #ManyToOne private Status status; Now I receiving the ERROR: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: #OneToOne or #ManyToOne on tj.eskhata.pos.domain.User.status references an unknown entity: tj.eskhata.pos.domain.Status
This message clearly shows that something goes wrong with Status that isn't recognized as an Entity (and thus can't be referenced in an association, preventing the session factory from being instantiated). This is usually due to a configuration or mapping problem. So:
Do you declare entities somewhere (in hibernate.cfg.xml or in persistence.xml)? If yes, did you declare Status? If you are using classpath scanning, is Status scanned?
Double-check the mapping, check that the column names really exist (it's unclear if you are using an existing physical model).
Activate logging (Spring Logging, Hibernate Logging), this is helpful during development and will help to find the problem.