I am using spring-data-jpa and JPA repositories
here is my source code
<beans:bean id="producerService" class="cz.services.RepositoryProducerService" />
<jpa:repositories base-package="cz.repository" />
<beans:bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="packagesToScan" value="cz.models" />
<beans:property name="jpaVendorAdapter">
<beans:bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</beans:property>
<beans:property name="jpaProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<beans:property name="entityManagerFactory" ref="myEmf" />
</beans:bean>
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url"
value="jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8" />
<beans:property name="username" value="root" />
<!--<property name="password" value="test" /> -->
<beans:property name="password" value="test"></beans:property>
</beans:bean>
and here is my entity and repository classes:
package cz.models;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the users database table.
*
*/
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private int enabled;
private String password;
private String username;
//bi-directional many-to-one association to Authority
#OneToMany(mappedBy="user")
private List<Authority> authorities;
//bi-directional many-to-one association to Room
#OneToMany(mappedBy="user")
private List<Room> rooms;
//bi-directional many-to-one association to UsersData
#OneToMany(mappedBy="user")
private List<UsersData> usersData;
public User() {
}
....
public List<Room> getRooms() {
return this.rooms;
}
and here are User Repository:
public void setRooms(List<Room> rooms) {
this.rooms = rooms;
}
public Room addRoom(Room room) {
getRooms().add(room);
room.setUser(this);
return room;
}
public Room removeRoom(Room room) {
getRooms().remove(room);
room.setUser(null);
return room;
}
public List<UsersData> getUsersData() {
return this.usersData;
}
public void setUsersData(List<UsersData> usersData) {
this.usersData = usersData;
}
public UsersData addUsersData(UsersData usersData) {
getUsersData().add(usersData);
usersData.setUser(this);
return usersData;
}
public UsersData removeUsersData(UsersData usersData) {
getUsersData().remove(usersData);
usersData.setUser(null);
return usersData;
}
}
and userRepository:
public interface UserRepository extends JpaRepository<User, Integer> {
#Transactional
#Query("select u from User u WHERE u.enabled = 1 ")
public List<User> findAllactiveUsers();
#Transactional
#Query("select u from User u WHERE u.username = :username ")
public User findByUsername(#Param("username")String username);
}
and my service for spring security:
#Service
public class MyUserDetailsService implements UserDetailsService {
#Resource
UserRepository repositoryUser;
#Resource
AuthorityRepository repositoryAuthority;
public UserDetails loadUserByUsername(String username) {
System.out.println("start");
cz.models.User userModel = null;
UserDetails userDetail = null;
try{
userModel = repositoryUser.findByUsername(username);
// User user = userModel;
System.out.println(userModel.getUsername());
List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);
// repositoryUserData.findAll();
System.out.println(userModel.getAuthorities().size());
Collection<SimpleGrantedAuthority> collectionAuthorities = new ArrayList<SimpleGrantedAuthority>();
for (int i = 0; i < authorities.size(); i++) {
collectionAuthorities.add(new SimpleGrantedAuthority(authorities
.get(i).getAuthority()));
}
userDetail = new User(userModel.getUsername(),
userModel.getUsername(), collectionAuthorities);
}catch(Exception e){
e.printStackTrace();
}
return userDetail;
}
}
The problem is: when I want call - this peace of code:
userModel.getAuthorities()
which call child (fk in db). I have exception :
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
When I add second repository Authorities I do not have this no session problem. But I do not want create every time method in my repository.
List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);
I have to use hibernate.LazyInitialization instead of eanger.(and some stable)
I saw a lot of post with this problem with JPA, but nothing work for me :(
Use a query that fetches the data you want so that it is there when you need it.
#Query("select u from User u left join fetch u.authorities WHERE u.username = :username ")
public User findByUsernameFetchAuthorities(#Param("username")String username);
Using findByUsernameFetchAuthorities when you want to access the authorities will cause them to be pre-fetched, avoiding the error and keeping them lazily fetched for every other query.
Related
I am using Hibernate as an ORM for a Spring Boot Application to write values to my Postgres Database.I have configured the properties in my persistence.xml
Persistence.xml
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/ImageHoster" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="postgres" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
I have created an entity called Movie
Movie
#Entity
#Table(name = "Movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
public String id;
#Column(name = "movie")
public String movie;
#Column(name = "updatedDate")
public Date updatedDate;
#Lob
#Column(name = "image")
public String image;
public String getMovie() {
return movie;
}
public void setMovie(String movie) {
this.movie = movie;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
At the first time when there is no movie table in my postgres database the table is getting created and there is no error.But as i am running the application once the table is created it is trying to create the table again which is causing the below error
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement.
My Configuration for the JPA goes like this
JPAConfig
#Configuration
public class JpaConfig {
#Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf =new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
emf.afterPropertiesSet();
return emf.getObject();
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl("jdbc:postgresql://localhost:5432/ImageHoster");
ds.setUsername("postgres");
ds.setPassword("postgres");
return ds;
}
}
Any idea where i am going wrong as I have another entity called User which is working fine and is not getting created everytime the application runs.
Once i changed the table name from Movie to movie in my entity everything was working as expected.
#Entity
#Table(name = "movie"){
}
This made everything fine..any idea why this happened? as i am not able to understand why it is a problem.
I have a spring boot application using hibernate as it's ORM framework. It exposes a RESTful API, one of the methods inserts new messages into the table.
The problem I am having is that it performs a call to Oracle to retrieve the nextval for the sequence number, then when it inserts that it uses the first number from that pool, then when another requests comes in, it takes the value of the next nextval instead of using the next value from the initial pool. So it should go 100, 101, 102, etc... but instead it goes like that 100,200,300 (the allocation size is 100).
All the beans are singletons including the DAO that persists the messages.
#Entity
#Table(name = "MESSAGE")
public class Message implements Serializable {
#Id
#SequenceGenerator(name = "MESSAGEID_GENERATOR", sequenceName = "SEQ_MESSAGE", allocationSize = 100)
#GeneratedValue(generator = "MESSAGEID_GENERATOR", strategy = GenerationType.SEQUENCE)
#Column(name = "MESSAGEID", unique = true, nullable = false, precision = 10)
private Long messageid;
}
Dao:
#Repository
public class MessageDao {
#PersistenceContext(unitName = "ORM_Model")
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
return entityManager;
}
#Transactional
public long save(Message message) {
entityManager.persist(message);
entityManager.flush();
return message.getMessageid();
}
}
persistance.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="ORM_Model">
<description>The IFIS Database Entity Model</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.package.Message</class>
<properties>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.transaction.flush_before_completion" value="true" />
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
</persistence>
Any idea what could be the problem here?
Regards!
Set your allocationSize=1 to solve your issue.
I am currently working on an API implementation in Java with spring and hibernate.
I have two tables in my Model package
User and UserDetail which has a OneToMany mapping
#Entity
public class User {
private Long id;
private String userId;
private Set<UserDetail> userDetails;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "user")
public Set<UserDetail> getUserDetails() {
return userDetails;
}
public void setUserDetail(Set<UserDetail> userDetails) {
this.userDetails = userDetails;
}
}
#Entity
public class User {
private Long id;
private String key;
private String value;
private User user;
#ManyToOne
#JoinColumn(name = "USER_ID", nullable = false)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
My API looks like this
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void addUserDetail(AddUserDetailRequest request) {
//... adds the user detail for the userId as request.getUserId()
}
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
//... deletes a particular value for a user with userId as request.getUserId() and userDetail key as request.getDeleteKey()
}
I have written Junit test cases to test the addition and deletion of UserDetails for a user, My addUserDetail is working as it should, but when I call the delete the changes are not reflected and they fail.
Below is my test case
#Test
public void testDeletUserDetail() throws Exception {
//GIVEN
String userId = client.newUser().call(getCreateUserRequest()).getId();
client.newAddUserDetail().call(getAddUserDetailRequest(userId, "key1", "value1"));
client.newAddUserDetail().call(getAddUserDetailRequest(userId, "key2", "value2"));
//WHEN
client.newDeteteUserDetail().call(getDeleteUserDetailRequest(userId, "key2"));
//THEN
List<UserDetail> userDetails = client.newGetUserDetail().call(getGetUserDetailRequest(userId));
assertEquals(userDetails.size(), 1); // This check fails and says it has a size of 2 instead of 1.
}
I am using HSQL for testing purposes
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.iiitd.myAPI.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL" />
<property name="generateDdl" value="true" />
<property name="showSql" value="false" />
</bean>
</property>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL" />
I have two implementation for deleteUserDetail and one of them fails.
// This one works in both jUnit and manual testing
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
User user = userRepository.findByUserId(request.getUserId());
if(!CollectionUtils.isEmpty(user.getUserDetail())) {
UserDetail toRemove = null;
for(UserDetail userDetail : user.getUserDetail()) {
if(StringUtils.equals(userDetail.getKey(), request.getDeleteKey())) {
toRemove = userDetail;
}
}
Assert.notNull(toRemove, "Detail user doesn't exist.");
user.getUserDetail().remove(toRemove);
userRepository.save(user);
}
}
//This one doesn't and unit tests fails but manual tests are OK
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
UserDetail userDetail = userDetailRepository.getUserDetail();
Assert.notNull(userDetail, "Detail doesn't exists");
userDetailRepository.delete(userDetail);
}
All the repositories extends JpaRepository
Could anyone explain how to circumvent this issue ?
Any help would be appreciated.
I am attempting to handle an 'entity' through annotation instead of a hibernate xml mapping.
I face a situation where addition succeeds but retrieval fails - help is appreciated.
Model class:
#Entity
#Table(name = "PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = -5527566248002296042L;
#Id
#Column(name = "ID")
#GeneratedValue
private Integer id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "MONEY")
private Double money;
.....setters and getters
}
spring configuration:
<context:annotation-config />
<context:component-scan base-package="org.spring.entity,org.spring.service" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
....
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
...
<property name="packagesToScan">
<list>
<value>org.spring.entity</value>
<value>org.spring.service</value>
</list>
</property>
<property name="hibernateProperties">
...
</property>
</bean>
Service class:
public void add(String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Create a new person
Person person = new Person();
person.setFirstName(firstName);
person.setLastName(lastName);
person.setMoney(money);
// Save
session.save(person);
}
finally{
session.close();
}
}
public void edit(Integer id, String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Retrieve existing person via id
Query query = session.createQuery("FROM Person WHERE ID=?");<=FAILS HERE
query.setInteger(0, id);
Person person = (Person)query.list().get(0);
......
}
The error is as below:
Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException:
person is not mapped [from person where ID=?]
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClass
Persister(SessionFactoryHelper.java:180)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement
(FromElementFactory.java:110)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromCla
use.java:93)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlW
alker.java:324)
Your HQL is wrong, Do this way:
(in case of multiple results, their might be some syntax left right, please check.)
Query query = session.createQuery("FROM Person WHERE ID=:ID")
List list=query.setParameter("ID",ID).list();
or
(in case of Single result)
Person person =new Person ();
person =(Person ) session.get(Person .class, ID);
I'm working on a project using spring hibernate & jpa and I'm deploying it on cloud foundry. My problem is that when I call the Dao to persist my entity to the mysql database nothing happens. No errors are thrown, I've tried wrapping the persist in a try catch block and nothing.
I have the show sql property in persistance.xml set to true. When I other Dao methods that just query the database I can see the SQL that gets run. But when I try the persist no SQL gets wrote to the console.
Sample console feedback from a query
Hibernate: select animal0_.animal_id as animal1_1_, animal0_.about as about1_, animal0_.animaltype as animaltype1_, animal0_.breed as breed1_, animal0_.date_in as date5_1_, animal0_.date_out as date6_1_, animal0_.image_1 as image7_1_, animal0_.image_1_content_type as image8_1_, animal0_.image_1_file_name as image9_1_, animal0_.image_1_file_size as image10_1_, animal0_.image_2 as image11_1_, animal0_.image_2_content_type as image12_1_, animal0_.image_2_file_name as image13_1_, animal0_.image_2_file_size as image14_1_, animal0_.image_3 as image15_1_, animal0_.image_3_content_type as image16_1_, animal0_.image_3_file_name as image17_1_, animal0_.image_3_file_size as image18_1_, animal0_.name as name1_, animal0_.status as status1_ from animals animal0_
INFO : com.lasthope.web.animals.service.AnimalsServiceImpl - Found 0 animals in care.
Sample console feedback from the persist:
INFO : com.lasthope.web.animals.service.AnimalsServiceImpl - Saving Gerry to database.
INFO : com.lasthope.web.animals.dao.AnimalsDaoImpl - DAO, saving animal Gerry ID: null
Any feedback would be greatly appreciated!
root-context.xml:
<cloud:data-source id="dataSource" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
Service:
#Service("animalsService")
public class AnimalsServiceImpl implements AnimalsService {
#Autowired
private AnimalsDao animalsDao;
#Override
#Transactional
public void saveAnimal(Animal animal) {
logger.info("Saving "+animal.getName()+ " to database.");
animalsDao.saveAnimal(animal);
}
DAO:
#Repository("animalsDao")
public class AnimalsDaoImpl implements AnimalsDao {
private static final Logger logger = LoggerFactory.getLogger(AnimalsDaoImpl.class);
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public void saveAnimal(Animal animal) {
logger.info("DAO, saving animal " +animal.getName() +" ID: " +animal.getAnimalId());
getEntityManager().persist(animal);
}
persistance.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
Animal class:
#Entity
#Table(name="animals")
public class Animal implements Serializable {
#Id
#Column(name = "ANIMAL_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer animalId;
#Column(name = "ANIMALTYPE")
private String animalType;
#Column(name = "BREED")
private String breed;
#Column(name = "NAME")
private String name;
#Column(name = "IMAGE_1")
#Lob
private Blob image1;
#Column(name = "IMAGE_1_CONTENT_TYPE")
private String image1ContentType;
#Column(name = "IMAGE_1_FILE_NAME")
private String image1FileName;
#Column(name = "IMAGE_1_FILE_SIZE")
private String image1FileSize;
#Column(name = "IMAGE_2")
#Lob
private Blob image2;
#Column(name = "IMAGE_2_CONTENT_TYPE")
private String image2ContentType;
#Column(name = "IMAGE_2_FILE_NAME")
private String image2FileName;
#Column(name = "IMAGE_2_FILE_SIZE")
private String image2FileSize;
#Column(name = "IMAGE_3")
#Lob
private Blob image3;
#Column(name = "IMAGE_3_CONTENT_TYPE")
private String image3ContentType;
#Column(name = "IMAGE_3_FILE_NAME")
private String image3FileName;
#Column(name = "IMAGE_3_FILE_SIZE")
private String image3FileSize;
#Column(name = "ABOUT")
private String about;
#Column(name = "DATE_IN")
private Date dateIn;
#Column(name = "DATE_OUT")
private Date dateOut;
#Column(name = "STATUS")
private String status;
Got it working! Finally!
Here is a summary of the changes I had to make.
In Animal class (entity object) I changed the id field from a Integer to a long. (I doubt that was anything to do with the fix though!) and removed the implements Serializable.
In the root context I changed the tx from
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
to
<tx:annotation-driven/>
and I added
<context:component-scan base-package="com.lasthope.web"/>
Then in my servlet context I added
<context:component-scan base-package="com.lasthope.web.controllers" />
It looks like it was a clash between the compenet scans.
Why it worked while pointing to an Oracle database I will never know.
Try setting the GeneratedValue strategy to identity, make sure the ANIMAL_ID column is specified as an autonumber.
#Id
#Column(name = "ANIMAL_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer animalId;
Also, if your using a new version of mySql (v5.x+), in the persistence.xml file you should specify the dialect as:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
Try creating a transaction when persisting:
public void saveAnimal(Animal animal) {
logger.info("DAO, saving animal " +animal.getName() +" ID: " +animal.getAnimalId());
EntityManager em = getEntityManager();
em.getTransaction().begin();
em.persist(animal);
em.getTransaction().commit();
}