Reputation: 155
I'm trying to learn spring-boot basic annotation configuration with hibernate, to make myself a template that will always work.
I'm using spring-boot latest release version 1.51 on STS (spring tool suite) 3.8.3.
Here is my main:
@SpringBootApplication
@EnableAutoConfiguration
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Now, I know that @SpringBootApplication
automatically comes with @componetScan
, so I didn't add it.
My configuration class:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "someEntityManagerFactory", transactionManagerRef = "someTransactionManager", basePackages = {
"com.example.*" })
@EntityScan(basePackages = "com.demo.models")
@ConfigurationProperties(prefix = "mysql.datasource")
public class DataBaseConfig {
@Autowired
private Environment env;
@Bean
public DataSource someDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("mysql.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("mysql.datasource.url"));
dataSource.setUsername(env.getProperty("mysql.datasource.username"));
dataSource.setPassword(env.getProperty("mysql.datasource.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean someEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(someDataSource());
em.setPackagesToScan(new String[] { "org.openlegacy.analytics.models" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public PlatformTransactionManager someTransactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(someEntityManagerFactory().getObject());
tm.setDataSource(someDataSource());
return tm;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
properties.setProperty("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.setProperty("spring.jpa.show-sql", env.getProperty("spring.jpa.show-sql"));
properties.setProperty("spring.jpa.hibernate.naming.physical-strategy",
env.getProperty("spring.jpa.hibernate.naming.physical-strategy"));
return properties;
}
}
My controller class:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRipository;
@RequestMapping(value = "", method = RequestMethod.GET)
public List<User> getItems() {
return userRipository.getUsers();
}
@RequestMapping(value = "/message", method = RequestMethod.GET)
public String getMessage() {
return userRipository.getMessage();
}
}
My repository class:
@Transactional
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager entityManager;
@SuppressWarnings("unchecked")
public List<User> getUsers() {
return entityManager.createQuery("select u from User u").getResultList();
}
public String getMessage() {
return "hello";
}
}
My entity class:
@Entity(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "user_name")
private String userName;
@Column(name = "password")
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
and my properties file:
# DataSource settings: set here your own configurations for the database connection.
mysql.datasource.username=openlegacy
mysql.datasource.password=openlegacy
mysql.datasource.driver-class-name=com.mysql.jdbc.Driver
mysql.datasource.url=jdbc:mysql://localhost:3306/olbank
spring.jpa.database= MYSQL
spring.data.jpa.repositories.enabled=true
#spring.jpa.database-platform=org.hibernate.dialect.MYSQL5Dialect
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
#spring.jpa.hibernate.naming.strategy= org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.hibernate.naming.physical-strategy= org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
and when I'm tying to retrieve data from the user table, I get this error:
org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped...
My questions are:
why am I getting this error? I know that user is mapped by the class name, and that's what I'm doing
is this the best way to configure hibernate with spring-boot? It's important for me to write code by the best practices.
Please give a detailed answer so I can learn from it.
Any other information that can be useful is welcome :)
Thanks.
Upvotes: 3
Views: 37662
Reputation: 7
In my case, with the entity name was not working, so i added instead entity.class.getName();
Upvotes: 0
Reputation: 39
If you are using JPQL then don't forget to add nativeQuery=true
after your JPQL query in repository interface.
Example:-
@Query(value="SELECT ID, NAME FROM USER", nativeQuery=true)
Object getUser();
Upvotes: 1
Reputation: 194
In my case, i had to add the name for the Entity. @Entity(name = "users")
@Entity(name = "users")
@Table(name = "users")
public class User implements Serializable{
}
UPDATE If you leave the entity without name and write the class name, it also should work .
@Entity
@Table
public class User implements Serializable{
}
and then
@query("select u from User u")
Upvotes: 1
Reputation: 2126
With Spring boot JPA
, by default, each query will refer to the column or the variable that is defined in an @Entity
class that mapped to each column in the database.
However, it is possible to use a native query or raw query
public interface UserInfoRepository extends CrudRepository<UserModel, String>
@Query("SELECT ID, NAME FROM USER", nativeQuery = true)
Optional<List<UserModel>> findSomething();
}
The columns ID and Name are the column name according to the database (Native Query)
Example of using EntityManager
Query query = em.createNativeQuery("SELECT ID, NAME FROM USER")
application.yml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
username: username
password: pass
hikari:
idle-timeout: 1000
maximum-pool-size: 10
minimum-idle: 2
pool-name: pool-name
jdbc-url: jdbc:oracle:thin:@localhost:1521:INSTANCE
driver-class-name: oracle.jdbc.OracleDriver
@Entity
class using lombok
or without lombok (manually create getter, setter functions)@Data
@NoArgsConstructor
@EntityScan
@Entity(name = "USER")
public class UserInfoModel {
@Id
@Column(name = "USERID")
private long userId;
@Column(name = "NAME")
private String name;
@Column(name = "DEPT")
private String dept;
}
public interface UserInfoRepository extends CrudRepository<UserInfoModel, Long> {
}
@Service
class to wrapp around a repository as a business layer and do your logic here@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserInfoRepository userInfoRepo;
@Override
public List<UserInfoModel> getUserInfo(long userId) throws Exception {
Optional<List<UserInfoModel>> info = userInfoRepo.findById(userId);
if (!info.isEmpty() && info.get().size() > 0) {
return info.get();
}
return null;
}
}
@Service
class in your controller
@RestController
@RequestMapping("/webint")
public class UserController {
@Autowired
private UserService userService;
}
Hope, this guides someone having trouble like me a few weeks ago
Upvotes: 0
Reputation: 16
Did you try bellow for entity:
@Entity
@Table(name = "user")
public class User implements Serializable {
}
Upvotes: 0
Reputation: 92
Spring JPA is case sensitive, so be sure you wrote the exact package URL and the correct class name.
Upvotes: 2
Reputation: 2261
Ok. You have a few things that need to be addressed in your overall configuration. You currently are providing an alias to your Entity User
@Entity(name = "user")
That is fine but if you are going to provide a name to your Entity then that is how you need to reference it in JPQL so, "select u from User u" would need to become
select u from user u
I might just suggest getting rid of your name qualifier and leave your query as "select u from User u".
Then secondly you do have some issues with package references:
@EnableJpaRepositories
annotation change your basePackages
to reference the base of your actual repository package, guessing
"com.demo.repository"
. Get rid of the wildcard reference.In your someEntityManagerFactory() method you are setting the
basePackage to (something I imagine is incorrect)
"org.openlegacy.analytics.models".
You indicated your entity(s) is
under "com.demo.models"
. So you should change that setter to
em.setPackagesToScan(new String[] { "com.demo.models" });
That should do the trick.
Upvotes: 18