What is the Java #Configuration equivalent to:
<repositories base-package="com.acme.repositories" />
in Spring Data JPA? I am trying to get rid of XML configuration in favour to #Configuration classes, however reading through JpaRepositoryConfigDefinitionParser sources is fruitless.
The closest what I can get is:
#Bean
public RepositoryFactorySupport repositoryFactory() {
return new JpaRepositoryFactory(entityManagerFactory().createEntityManager())
}
#Bean
public BookDao bookDao() {
return repositoryFactory().getRepository(BookDao.class)
}
However the <repositories/> tag is much more functional: it automatically creates DAO for all interfaces extending CrudRepository found on CLASSPATH. Also it seems like my solution does not apply transactions to DAOs as opposed to default Spring Data JPA behaviour.
Spring Data JPA introduced #EnableJpaRepositories. See the reference documentation for details.
Looks like not possible yet: https://jira.springsource.org/browse/DATAJPA-69
Related
I am trying to learn to migrate one spring XML based application to spring boot application and wondering with one scenario where we have multiple constructors in a class and wish to inject all these using spring annotation.
I do understand and implemented the way using XML based configuration but confused with which annotation/way to inject multiple constructors.
I tried referring to few forums like : Ambiguity Regarding Spring Constructor Injection but no luck with spring boot.
Could anyone please help on this please?
As it was mentioned in comments you can use #Configuration
#Configuration
public class Config {
#Bean
public Employee employee() {
return new Employee(10,"100");
}
}
I have a custom naming strategy in a Spring app with Hibernate:
public class MyCustomPhysicalNamingStrategy implements PhysicalNamingStrategy {
#Override
public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
return Identifier.toIdentifier("my_custom_table_name");
}
// ...
}
The Spring documentation says I can tell Hibernate to use it either by setting spring.jpa.hibernate.naming.physical-strategy (which works fine), or like this:
Alternatively, if ImplicitNamingStrategy or PhysicalNamingStrategy beans are available in the application context, Hibernate will be automatically configured to use them
I need to use this second method, as I need to pass some info from Spring's context to my naming strategy. However, I can't get it to work.
I'm creating the bean in the following configuration class:
#Configuration
public class PersistenceConfiguration {
#Bean
public PhysicalNamingStrategy physicalNamingStrategy() {
return new MyCustomPhysicalNamingStrategy();
}
}
What am I missing here?
Thanks in advance.
EDIT: I'm on Spring Boot/Spring JPA 1.5.9.RELEASE, which gives me Hibernate core v.5.0.12.Final and Hibernate JPA API 2.1.
It seems that this is only supported with spring boot 2.
See: https://github.com/spring-projects/spring-boot/blob/v2.0.3.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.java#L95
This file is not present in spring boot 1.5: https://github.com/spring-projects/spring-boot/tree/v1.5.14.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa
(HibernateJpaAutoConfiguration.java doesn't have it)
I am having a hard time deciding if I should stick with Hibernate for a new project, or get my feet wet with JPA and the new Spring Data implementation.
Is the Spring Data framework intended for large projects or small projects with modest query requirements?
While I certainly see the advantage in code reduction by using the #Query annotation, what do you do for dynamic queries? What about when you want to implement a save() method that's quite complex?
The documentation says to make a Custom interface and implementation that your main repository implements, but what if you need to access any super methods on the crud repository itself? The crud repository implements the custom one - not the other way around. It seems like an odd design.
I am very uncertain whether this framework will meet the challenges of complex and large applications. I've never ran into many problems with Hibernate, and I'm considering sticking with the good old reliable rather than go with Spring Data JPA.
What should I do? What unforeseen complications and costs will I encounter if I go with Spring Data JPA?
So, spring-data does some extra magic that helps with complex queries. It is strange at first and you totally skip it in the docs but it is really powerful and useful.
It involves creating a custom Repository and a custom `RepositoryImpl' and telling Spring where to find it. Here is an example:
Configuration class - point to your still-needed xml config with annotation pointing to your repositories package (it looks for *Impl classes automatically now):
#Configuration
#EnableJpaRepositories(basePackages = {"com.examples.repositories"})
#EnableTransactionManagement
public class MyConfiguration {
}
jpa-repositories.xml - tell Spring where to find your repositories. Also tell Spring to look for custom repositories with the CustomImpl file name:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<jpa:repositories base-package="com.example.repositories" repository-impl-postfix="CustomImpl" />
</beans>
MyObjectRepository - this is where you can put annotated and unannotated query methods. Note how this repository interface extends the Custom one:
#Transactional
public interface MyObjectRepository extends JpaRepository<MyObject, Integer>, MyObjectRepositoryCustom {
List<MyObject> findByName(String name);
#Query("select * from my_object where name = ?0 or middle_name = ?0")
List<MyObject> findByFirstNameOrMiddleName(String name);
}
MyObjectRepositoryCustom - repository methods that are more complex and cannot be handled with a simple query or an annotation:
public interface MyObjectRepositoryCustom {
List<MyObject> findByNameWithWeirdOrdering(String name);
}
MyObjectRepositoryCustomImpl - where you actually implement those methods with an autowired EntityManager:
public class MyObjectRepositoryCustomImpl implements MyObjectRepositoryCustom {
#Autowired
private EntityManager entityManager;
public final List<MyObject> findByNameWithWeirdOrdering(String name) {
Query query = query(where("name").is(name));
query.sort().on("whatever", Order.ASC);
return entityManager.find(query, MyObject.class);
}
}
Amazingly, this all comes together and methods from both interfaces (and the CRUD interface, you implement) all show up when you do:
myObjectRepository.
You will see:
myObjectRepository.save()
myObjectRepository.findAll()
myObjectRepository.findByName()
myObjectRepository.findByFirstNameOrMiddleName()
myObjectRepository.findByNameWithWeirdOrdering()
It really does work. And you get one interface for querying. spring-data really is ready for a large application. And the more queries you can push into simple or annotation only the better off you are.
All of this is documented at the Spring Data Jpa site.
I've used Spring Data JPA in small and large projects with simple query demands. The main advantage is from not even having to use the #Query annotation. There is nothing in Spring Data that prevents you from using it in large projects and the recent QueryDSLsupport might help you. This is an example of using QueryDSL to target Hibernate.
If you foresee complex queries and you feel comfortable using Hibernate objects without JPA I think an alternative combination could be to have the simple Spring Data Repositorys next to complex Hibernate-based ones with the specific methods you might need. It might be less cumbersome that twisting a Hibernate implementation into Spring Data JPA structure.
Spring JPA will provide you a lot of abstraction from writing SQL and even some HQL using query method declaration. Spring JPA shines with its query generation but when you want a purely hibernate solution you can customize as needed as spring JPA is still based on hibernate. Check the docs http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html for more info.
I have a scenario configuring Spring Security on embedded Jetty which seems to be somewhat solved if I make use of JavaConfig to configure the Jetty server.
As a result, it's looking like JavaConfig rather than XML might be the better option for large chunks of the project. However, there are some niceties in the XML namespaces, like <context:component-scan /> which aren't readily available in a #Configuration setting.
I have discovered that ApplicationContextAware is honored for #Configuration classes, so the following is possible
#Configuration
public class FooConfig implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
((AnnotationConfigApplicationContext) applicationContext).scan("org.example");
}
}
The alternative, which is documented, is to have the #Configuration class use an #ImportResource annotation and pull in an existing XML file:
#Configuration
#ImportResource("applicationContext-withComponentScan.xml")
public class BarConfig {}
I guess the question is "Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse"? Something just feels oddly dirty about the approach so I'd not be surprised if the Spring guys had covered this in some way or another that I've not spotted.
For the interested, the problem relates to scanning a Jersey setup with #Resource and #Provider classes that I'd rather not have to manually manage entries in a class/XML configuration.
Now that Spring 3.1 is ready and out, you can safely use #ComponentScan if you are on Spring 3.1. It's not only for Spring MVC as one of the outdated answers mentions. You can use it as follows:
#Configuration
#ComponentScan({"com.foo.bar", "org.foo.bar"})
public class AppConfig{ /** config code */ }
Here is the documentation http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/ComponentScan.html
Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse
Yes, this is bad form. If you're going to fetch things out of the context manually, you may as well not bother with dependency injection in the first place.
However, your second option (#ImportResource("applicationContext-withComponentScan.xml")) is a good one - this is current best practice when you want to use these XML macros in combination with annotation-style config.
A third option is to use the current milestone build of Spring 3.1, which adds a way of doing these things all in Java, using #Feature. This is not yet production-ready, though.
Check this link out as well. It is a bit more specific (for a web application) but it has a very nice code example for the scanning, specifically: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
from that link:
#ComponentScan(basePackages = { "org.example"} )
So in the latest version of Spring we are able to use the #Configuration annotation to setup our configurations for Spring. Now in JavaConfig it is possible to use the #AnnotationDrivenTx (#AnnotationDrivenTx Reference Link) annotation to setup transactions in our Config class. But since JavaConfig has been decommissioned I was wondering if anyone knew how to setup something similar without JavaConfig and without needing to add anything to the application-context.xml. Here is what I basically have for my Config class
#Configuration
#ImportResource("config/application-context.xml")
public class Config {
public #Bean DataSource dataSource() {
//get and return datasource
}
public #Bean Service1 getService1() {
//return service1Impl
}
}
And I'd like to make Service1 transactional. If anyone has any ideas on how to do this or if this is just not possible please let me know.
Thanks!
You can now use #EnableTransactionManagement.
See this post for more details: http://blog.springsource.com/2011/06/10/spring-3-1-m2-configuration-enhancements/
It seems like it isn't possible according to this forum post:
there may be a more first-class
mechanism for enabling
annotation-driven TX in #Configuration
classes in Spring 3.1, but in the
meantime, the recommended approach is
to use #ImportResource to include a
snippet of XML that declares
<tx:annotation-driven/>
Wait: but you seem to have an XML context anyway. Why not add <tx:annotation-driven/> to it and use #Transactional?
Take a look at http://blog.springsource.com/2011/02/17/spring-3-1-m1-featurespec. Spring 3.1's FeatureSpecification classes such as TxAnnotationDriven are designed to solve exactly the problem described above.