我最近开始使用Spring Boot,但是遇到了一些问题。以前,当我仅将Spring数据与hibernate和JPA一起使用时,我可以创建一个hibernate.cfg.xml文件,该文件将提供一堆可以传递给config对象的配置,然后最终创建一个SessionFactory对象,该对象将创建一个可用于将查询传递给hibernate状态的会话对象:
package util; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml Configuration configuration = new Configuration().configure("hibernate.cfg.xml"); return configuration.buildSessionFactory( new StandardServiceRegistryBuilder().applySettings( configuration.getProperties() ).build() ); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/hello-world</property> <property name="connection.username">root</property> <property name="connection.password">password</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Create/update tables automatically using mapping metadata --> <property name="hbm2ddl.auto">update</property> <!-- Use Annotation-based mapping metadata --> <mapping class="entity.Author"/> <mapping class="entity.Article"/> </session-factory> </hibernate-configuration>
Main.java
public class HelloWorldClient { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction txn = session.getTransaction(); EntityManagerFactory emf = Persiscance.createEntityManagerFactory("hibernate.cfg.xml"); EntityManager em = emf.createEntityManager(); EntityTransaction txn = em.getTransaction(); try { txn.begin(); Author author = new Author("name", listOfArticlesWritten); Article article = new Article("Article Title", author); session.save(author); session.save(article); Query query = session.createQuery("select distinct a.authorName from Article s where s.author like "Joe%" and title = 'Spring boot'); List<Article> articles = query.list(); txn.commit(); } catch(Exception e) { if(txn != null) { txn.rollback(); } e.printStackTrace(); } finally { if(session != null) { session.close(); } } } }
这是出现问题的地方。我不知道如何避免为自定义查询创建hibernate.cfg.xml文件或会话工厂。在Spring指南页面中,以及我已经完成的一些教程中,他们采用了DAO并扩展了CrudRepository接口,该接口已经提供了许多方法,以及一种命名方法的方法,以便Hibernate可以自行构建sql。 。
我要完成的工作,至少在这篇文章中是要能够在Spring Boot中执行上述查询。我可以创建一个属性文件
application.properties
# =============================== # = DATA SOURCE # =============================== # Set here configurations for the database connection spring.datasource.url = jdbc:mysql://localhost:3306/spring-boot-demo spring.datasource.username = test spring.datasource.password = test # Mysql connector spring.datasource.driverClassName = com.mysql.jdbc.Driver # =============================== # = JPA / HIBERNATE # =============================== # Specify the DBMS spring.jpa.database = MYSQL # Show or not log for each sql query spring.jpa.show-sql = true # Ddl auto must be set to "create" to ensure that Hibernate will run the # import.sql file at application startup #create-drop| update | validate | none spring.jpa.hibernate.ddl-auto = update # SQL dialect for generating optimized queries spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect # =============================== # = THYMELEAF # =============================== spring.thymeleaf.cache = false #debug=true
我可以将除映射之外的所有内容移动到属性文件,但是由于不再有会话对象,因此我不清楚如何编写查询。
如果您使用Spring Boot + Spring Data JPA,则可以通过使用属性将数据源(现在将其放入 hibernate.cfg.xml中 )配置到中。application.propertiesspring.datasource.*
spring.datasource.*
这将自动为您创建一个实体管理器。如果需要使用查询,可以使用Spring Data JPA的存储库,例如:
public interface ArticleRepository extends JpaRepository<Article, Long> { @Query("select s from Article s where s.author like ?1 and s.title = ?2") List<Article> findByAuthorAndTitle(String author, String title); }
现在,您可以自动连接存储库并使用给定的查询,如下所示:
List<Article> articles = repository.findByAuthorAndTitle("Joe%", "Spring boot");
如果您确实需要自定义查询,则可以使用JPA中的Predicate / Criteria API。Spring提供了这些谓词的包装版本,称为Specification。
为此,您可以ArticleRepository使用另一个接口扩展您的接口JpaSpecificationExecutor<Article>。这为您的存储库添加了一些额外的方法:
ArticleRepository
JpaSpecificationExecutor<Article>
Specification<Article> spec = Specifications.<Article>where((root, query, cb) -> { return cb.and( cb.like(root.get("author"), "Joe%"), cb.equal(root.get("title"), "Spring boot")); }); List<Article> articles = repository.findAll(spec);
这使您可以动态创建查询,尽管从您的问题来看,它似乎并不是您真正需要的。