I am getting into java here. Fun and frustrating all at the same time :)
I have a simple method called showUsernames():
public String showUsernames(){
TimesheetUserDAO su = new TimesheetUserDAO();
Session session = su.getSession();
setUsers(su.findByUsername(_users));
session.close();
return SUCCESS;
}
...however, I am having a time getting just the usernames out of the database. It is possible with the Hibernate DAO to get this correct? I am able to use su.findAll() and return everything.
Any thoughts? Need more code? Thanks :)
The DAO probably executee a request like
select u from User u where ...
Change the query to
select u.name from User u where ...
Of course, instead of having a List<User> as a result, you'll have a List<String>.
This is basic stuff described in the Hibernate reference documentation. Have you read it?
Also, getting the session from the DAO and closing it manually like this shows a design problem. This should be encapsulated by the service layer or, even better, by the declarative transaction handling.
Related
I understood like spring jdbcTemplate - queryForObject is only for read operation against DB. But if we supply any update query, that also works fine which returns the updated object as well. So, is it good approach to use? Pls check my code snippet below
Employee employee = namedParameterJdbcTemplate.queryForObject(updateQuery, params,
new BeanPropertyRowMapper<Employee>(Employee.class));
Please add your suggestions
I've read many answers here on stackoverflow but still haven't found the best solution to load lazy entities with Spring Mono and JPA/Hibernate.
I can fix it easily by eager fetching but I think that is not the best solution.
My problem now is that I cannot have Hibernate.initialize working either and am looking for a solution. My use case is very simple:
#Transactional
public Mono<User> getUserById(String id) {
log.debug("Get user by {}", id);
return Mono
.justOrEmpty(userRepository.findById(id))
.map(user -> {
Hibernate.initialize(user.getCustomer().get());
Hibernate.initialize(user.getCustomer().map(Customer::getCustomerSettings).get());
return user;
});
}
The thing is that the Customer is an optional so I don't know if that has any impact on it.
I have tested with and without transactional, with and without .get(), and don't have many more ideas of how to solve this the correct way at the moment.
Always get this error:
org.hibernate.LazyInitializationException: could not initialize proxy [com.example.project.customer.model.Customer#692e8725-a5fa-4c87-ac2d-b382b1c6bfbc] - no Session
Any ideas?
With Spring JPA is there an easy way to use native queries but maintaining database independence, for example by using the query which fits best?
At the moment I do this by checking the currently set Dialect from the Environment and call the proper method of my Repository:
public Foo fetchFoo() {
if (POSTGRES_DIALECT.equals(env.getRequiredProperty("hibernate.dialect"))) {
return repo.postgresOptimizedGetFoo();
}
return repo.getFoo();
}
This works but I have the feeling that there is a better way or that I am missing something. Especially because (Spring) JPA allows it to use native queries quite easily but that breaks one of its big advantages: database independence.
As per my understanding, this can be achieved simply by using #Transactional(readOnly=false) and then instead of calling session.createQuery, one can use session.createSQLQuery, as provided in this example.
Your sql can be any of your native query.
Hope this works for you. :)
#Override
#Transactional(readOnly = false)
public Long getSeqVal() {
Session session = entityManager.unwrap(Session.class);
String sql = "SELECT nextval('seqName')";
Query query = session.createSQLQuery(sql);
BigInteger big = (BigInteger) query.list().get(0);
return big.longValue();
}
This is just an idea: I do not know whether it works or not:
My idea would be having subinterfaces, one normal Spring-Data-JPA-interface with all methods for one entiy (without native query hints). Than I would crate a subinterface for every database, that "override" the database specific native statements. (This intrface would be empty if there are no DB specific statements). Then I would try configure Spring-JPA with some profiles to load the right specific interface (for example by a class-name or package-name-pattern)
This seems like a way to complicated way to get queries to work.
If you really want to use optimized queries make it at least transparant for your code. I suggest using named queries and create an orm.xml per database (much like Spring Boot uses to load the schema.xml for a different database).
In your code you can simply do
public interface YourRepository extends JpaRepository<YourEntity, Long> {
List<YourEntity> yourQueryMethod();
}
This will look for a named query with the name YourEntity.yourQueryMethod. Now in your orm.xml add the named query (the default one and in another one the optimized one).
Then you need to configure your LocalContainerEntityManagerFactory to load the specific one needed. Assuming you have a property defining which database you use, lets name it database.type you could do something like the following
<bean class="LocalContainerEntityManagerFactoryBean">
<property name="mappingResources" value="classpath:META-INF/orm-${database.type}.xml" />
... other config ...
</bean>
This way you can keep your code clean of the if/then/else construct and apply where needed. Cleans your code nicely imho.
I have CustomerEntity mapped to table customers in database. It has one-to-many relations to orders and addresses. Now I retreive customer with orders with next code:
DetachedCriteria criteria = DetachedCriteria.forClass(CustomerEntity.class);
criteria.add(Restrictions.eq("id", patientId));
criteria.createCriteria("orders", CriteriaSpecification.LEFT_JOIN).add(Restrictions.and(
Restrictions.isNull("deletedDate"),
Restrictions.or(Restrictions.isNull("old"), Restrictions.eq("old", BoolType.FALSE))));
CustomerEntity customer = queryDao.searchSingle(criteria);
QueryDAO:
public <T> T searchSingle(DetachedCriteria criteria) {
return (T) criteria.getExecutableCriteria(getCurrentSession()).uniqueResult();
}
But when I try to invoke customer.getAddresses() next exception is thrown:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: , no session or session was closed
It happens because by default hibernate isn't loaded one-to-many entities.
How can I without modifying Customer entity retreive his addresses too?
This exception occurs when you try to access the lazy-loading collection or field at the moment when session is not available already. My guess would be - the backend of your application loads data and closes the session, then you pass this data to frontend, for example, where there is no session already.
To resolve this, there are several possible ways to go:
Eager loading. Reliable, but possibly slow solution;
Changing the way session management is done. Consider strategy session-per-request which is suitable for typical web application. The question Create Hibernate-Session per Request contains information might be usable for you.
For information about another session management strategies, try reading this wiki page.
There are a few things that can assist you:
The use of Hibernate.initialize(customer.getAddresses())
You do not show where customer.getAddresses() is used ... so one other method is to use Hibernate Open Session in View (along with other session management strategies mentioned in the previous answer.
I am examining example Blog example of CouchDB. I use Ektorp at Spring for CouchDB. I wanted to implement it into my application. I have users at my couch db when I use that:
#GenerateView
#Override
public List<User> getAll() {
ViewQuery q = createQuery("all")
.descending(true)
.includeDocs(true);
return db.queryView(q, User.class);
}
However it returns just last record. Any ideas to get all users?
It works well problem was about db names that's written at Spring configuration file.