I'm using Spring data which is easy to use but i can't control it because i got error there
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Qualite.fonctions, could not initialize proxy - no Session
I know FetchType.EAGER will work but i want keep it lazy.
so how can i control the session in spring data
#RequestMapping(value="/loadfonction")
public #ResponseBody
Set<Fonction> loadfonction(Map<String, Object> model, HttpServletRequest request) {
Set<Fonction> fonctions = qualiteRepo.findOne(Integer.valueOf(request.getParameter("idquality"))).getFonctions();
System.out.println(fonctions.size());
return fonctions;
}
I even try #Transactional annotation but it didn't work:
#Transactional
#RequestMapping(value="/loadfonction")
This is a common problem with trying to open a view using the spring mvc framework. The control method closes the session before the view can display it. (Trying to keep the view out of the business logic) To get around it you can use the OpenSessionInViewFilter class.
Here is an article on how to implement it:
http://blog.cloudmate.pl/2010/09/hibernates-open-session-in-view-in.html
In your repository you cannot use query methods to initialize the collection. Instead you should define a query like that to fetch the collection with it. Change your query according to your domain, I can't really figure out how it should look for you.
#Query("SELECT q FROM Qualite q JOIN FETCH q.role WHERE q.fonctionId = (:fonctionId)")
public Qualite findById(#Param("fonctionId") String fonctionId);
You can't. The only way to avoid this problem is to do a query when you want to retrieve the Fonction objects.
Related
i started a project on spring boot using a rest a webservice, when i shared it between my team they puted some comments :
get method need to be grouped Ex : get/users & get/users/{id} will be get/users/{id}
remove put method & just use post Ex: post/users/0 add | post/users/{id} update
make a helper class for Jdbc Template and call it in the repository classes to centralize the code
pls guys help me to solve this i'm so confused, and thank you
get method need to be grouped Ex : get/users & get/users/{id} will be
get/users/{id}
I do not agree with this. /get/users will be returning List<User> and get/users/{id} will return User that matches with {id}
remove put method & just use post Ex: post/users/0 add |
post/users/{id} update
Post should be used when you create a new resource. POST is not idempotent. Each time you call a post a new resource will be created.
e.g. Calling POST /Users will create a new User every-time.
PUT on other hands works like upsert. Create if the resource is not present and update/replace if present. Put is idempotent and doesn't change the resource's state even if it's called multiple times.
make a helper class for Jdbc Template and call it in the repository
classes to centralize the code
Helper classes help to separate the concerns and achieve single responsibility.
However, JdbcTemplate is a ready to use abstraction of JDBC. I don't see any point in creating Helper. You can create a DataAccessObject (DAO) or Repository which has-a JdbcTemplate. Like the two Dao shown below
public class UserDao {
#Autowired
private JdbcTemplate jdbcTemplate;
public User findUserById(String id){}
public void addUser(User user){}
}
// -------
public class BooksDao{
#Autowired
private JdbcTemplate jdbcTemplate;
public List<Book> getAllBooksByType(String type){}
public void Book getBookByName(String name){}
}
Now, your Dao objects can be called from Controller or if you need to modify data before/after DB operation, best is to have a Service layer between Controller and Dao.
Don't bother too much about recommendations or rules. Stick to the basic OOPS concepts. Those are really easy to understand and implement.
Always:
Encapsulate data variables and methods working on those variables together
Make sure your class has a Single Responsibility
Write smaller and testable methods (if you can't write tests to cover your method, then something is wrong with your method)
Always keep the concerns separate
Make sure your objects are loosely coupled. (You are already using spring so just use the spring's auto-wiring)
In our application, all rest apis are of the form:
http://{context}/{product_id}/{rest_url_path}
I have to verify the {product_id} inside a Spring Security Filter/SpringMVC interceptor, by fetching the ProductDetails from DB for the product_id. The ProductDetails will be used inside Spring Controllers/Service classes.
I don't want to fetch the ProductDetails again inside Controllers/Service. So I want to store the ProductDetails object somewhere for that RequestScope.
I have 3 approaches in mind. But each have their pros and cons. Please let me know which one better out of the 3. Also suggest any alternative approach.
Approach-1:
Save the ProductDetails object inside request attribute.
Inside Controller, i can easily get the HttpRequest. Inside Service, I can get HttpRequest by:
#Autowired
HttpServletRequest request;
or
RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = null;
if (attribs instanceof ServletRequestAttributes) {
request = ((ServletRequestAttributes) attribs).getRequest();
}
But I don't want to have HTTP request dependency inside Service to make to code more independent from WebLayer logic.
Approach-2:
Use any in memory cache based on product_id to stored ProductDetails
But this I think a over kill only for this use case. Increasing unnecessary dependencies of a cache.
Approach-3:
Store the Object in a ThreadLocal variable to store request scope data.
But not sure if it correct this way.
Let me know an efficient approach to solve this problem
1st and 3rd are suitable for your problem statment but first one is more elegant as data will stored only for current request scope and will get automatically lost when server send response. You can also use threadLocal but you have to be cautious ,if you forget to remove object it will hang around in an environment that uses a thread pool.
The first approach you mentioned is more efficient way to access the same data in both filter and controller even though you have to inject the dependency of HttpservletRequest in SpringController.
If the data is very user specific like other user will not have access to those data in that case you should use ThreadLocal.
I am using JPA with Spring and saving an entity in a test. In the process of writing a test to validate that an entity's relationship with another entity is correctly set up, I have come across a problem that I come across frequently. I have a test method (set to rollback) that:
Creates entity
Saves entity
Flushes
Retrieves entity
Validates entity
The problem is that when I look at the Hibernate logs, I only see a single insert to the database where I'd expect to see an insert and then a select.
I know this is because Hibernate's trying to save me some time and knows that it's got the entity with the ID I'm trying to retrieve but that bypasses an important step: I want to make sure that the entity actually made it to the database and looks like what I thought it should. What's the best way to deal with this so I can test that the entity is actually in the database?
Note: I assume this involves somehow detaching the entity or telling Hibernate to clear its cache but I'm not sure how to do that when all I have access to is a JpaRepository object.
Some code:
public interface UserRepository extends JpaRepository<User, Long> {
//...
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = JpaConfig.class, // JpaConfig just loads our config stuff
loader = AnnotationConfigContextLoader.class)
#TransactionConfiguration(defaultRollback = true)
public class UserRepositoryTest {
#Test
#Transactional
public void testRoles() {
User user = new User("name", "email#email.com");
// eventually more here to test entity-to-entity relationship
User savedUser = userRepository.save(user);
userRepository.flush();
savedUser = userRepository.findOne(savedUser.getId());
Assert.assertNotNull(savedUser);
// more validation here
}
}
You basically want to test Hibernate's functionality instead of your own code. My first suggestion: don't do it! It is already tested and validated many times.
If you really want to test it, there are a couple of options:
Execute a query (rather than a get. The query will get executed (you should see it in the log) and the result interpreted. The object you get back would still be the same object you saved, since that is in the session.
You can evict the object from the session and then get it again. If you use SessionFactory.getCurrentSession(), you'll get the same season that the repository is using. With that you can evict the object.
You have two strategies:
issue a native SQL query therefor bypassing any JPA cache.
ensure the persistence context is cleared before reloading.
For (1) you can change your tests to extend the following Spring class which, in addition to automatically beginning/rolling back a transaction at the start/end of each test, will give you access to a Spring JdbcTemplate you can use to issue the native SQL.
http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.html
http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/jdbc/core/simple/SimpleJdbcTemplate.html
For (2) you can clear the persistence context by doing the following (where the EntityManagerFactory is injected into your test:
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory).clear();
See the following base test class which I normally use and demonstrates the above and also allows for populating the database with known data before each test (via DBUnit).
https://github.com/alanhay/spring-data-jpa-bootstrap/blob/master/src/test/java/uk/co/certait/spring/data/repository/AbstractBaseDatabaseTest.java
(In fact in the above I am actually creating a new JdbcTemplate by injecting a datasource. Can't remember why...)
I am wondering if there is a way to wrap all argument resolvers like for #PathVariables or #ModelAttributes into one single transaction? We are already using the OEMIV filter but spring/hibernate is spawning too many transactions (one per select if they are not wrapped within a service class which is be the case in pathvariable resolvers for example).
While the system is still pretty fast I think this is not necessary and neither consistent with the rest of the architecture.
Let me explain:
Let's assume that I have a request mapping including two entities and the conversion is based on a StringToEntityConverter
The actual URL would be like this if we support GET: http://localhost/app/link/User_231/Item_324
#RequestMapping("/link/{user}/{item}", method="POST")
public String linkUserAndItem(#PathVariable("user") User user, #PathVariable("item") Item item) {
userService.addItem(user, item);
return "linked";
}
#Converter
// simplified
public Object convert(String classAndId) {
return entityManager.find(getClass(classAndId), getId(classAndId));
}
The UserService.addItem() method is transactional so there is no issue here.
BUT:
The entity converter is resolving the User and the Item against the database before the call to the Controller, thus creating two selects, each running in it's own transaction. Then we have #ModelAttribute methods which might also issue some selects again and each will spawn a transaction.
And this is what I would like to change. I would like to create ONE readonly Transaction
I was not able to find any way to intercept/listen/etc... by the means of Spring.
First I wanted to override the RequestMappingHandlerAdapter but the resolver calls are well "hidden" inside the invokeHandleMethod method...
The ModelFactory is not a spring bean, so i cannot write an interceptor either.
So currently I only see a way by completely replacing the RequestMappingHandlerAdapter, but I would really like to avoid that.
And ideas?
This seems like a design failure to me. OEMIV is usually a sign that you're doing it wrong™.
Instead, do:
#RequestMapping("/link/User_{userId}/Item_{itemId}", method="POST")
public String linkUserAndItem(#PathVariable("userId") Long userId,
#PathVariable("itemId") Long itemId) {
userService.addItem(userId, itemId);
return "linked";
}
Where your service layer takes care of fetching and manipulating the entities. This logic doesn't belong in the controller.
how will i load my entities in my flex application using lazy loading .I have a deep object graph
GraniteDS, together with its data management framework, lets you transparently load your uninitiated associations: see documentation here. So, basically, you don't have to do anything special in order to initialize your lazy collections/proxies, you only need to access one of them on the client side (asking for the size of a collection for example) and it will trigger a call to the server and fetch the uninitialized data.
If you don't want or can't use transparent lazy-loading, you need to write a specific initialization method which must have access to an EntityManager, receive your entity as a parameter, initialize the required association and send the entity back to the client.
AFAIK it's impossible. You should have opened hibernate session to do this.
In my project I'm doing what you need this way:
I have spring service like this:
public interface SomeObjectManager {
List<SomeObject> getObjects(); // here we have lazy loading for SomeObject's properties
SomeObject getFullObject(long objectId); // here we're loading full object
}
Some properties of SomeObject use lazy loading. To load them I use HQL query like this:
SELECT s FROM SomeObject s
LEFT JOIN FETCH s.child children
LEFT JOIN FETCH children.items items
LEFT JOIN FETCH items.property
WHERE s.id=:id
This query forces hibernate to load properties defined lazy.
So if you don't need fully loaded SomeObject instances you use getObjects() method. If then you need details on concrete SomeObject instance you use getFullObject() method.
Hope this helps.