Dropwizard Hibernate Configuration - mysql

I am new to Dropwizard and so far everything was going well till I started messing with Hibernate and MySQL. My problem is: Hibernate won't create tables and consequently no columns in my DB.
The only warning I get when running my jar file is:
org.hibernate.cfg.environment hibernate.properties not found
But do I need it at all? As I am having all configuration and mapping already.
Here is my application class:
public class LibraryApplication extends Application<LibraryConfiguration> {
public static void main(String[] args) throws Exception {
new LibraryApplication().run(args);
}
#Override
public String getName() {
return "hello backend";
}
private final HibernateBundle<LibraryConfiguration> hibernate = new HibernateBundle<LibraryConfiguration>(Book.class){ //more entities can be added separated with a coma
public DataSourceFactory getDataSourceFactory(LibraryConfiguration configuration) {
return configuration.getDataSourceFactory();
}
};
#Override
public void initialize(Bootstrap<LibraryConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/webapp", "/", "index.html", "static"));
bootstrap.addBundle(hibernate);
}
#Override
public void run(LibraryConfiguration configuration,
Environment environment) {
final BookDAO dao = new BookDAO(hibernate.getSessionFactory());
final TestResource resource = new TestResource(
configuration.getTemplate(), configuration.getDefaultName());
final TemplateHealthCheck healthCheck = new TemplateHealthCheck(
configuration.getTemplate());
environment.healthChecks().register("template", healthCheck); //register the health check
environment.jersey().register(resource); //register the resource class
environment.jersey().register(new BookResource(dao));
}
}
YAML file:
server:
type: simple
rootPath: '/api/*'
applicationContextPath: /
connector:
type: http
port: 8080
template: Hello, %s!
defaultName: back-end
database:
# the name of your JDBC driver
driverClass: com.mysql.jdbc.Driver
# the JDBC URL
url: jdbc:mysql://localhost:3306/books
# the username
user: root
# the password
password: root
# any properties specific to your JDBC driver:
properties:
charSet: UTF-8
hibernate.dialect: org.hibernate.dialect.MySQLDialect #org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.hbm2ddl.auto: create
Configurtion class:
public class LibraryConfiguration extends Configuration{
#Valid
#NotNull
#JsonProperty
private DataSourceFactory database = new DataSourceFactory();
#JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
}
#NotEmpty
private String template;
#NotEmpty
private String defaultName = "";
#JsonProperty
public String getTemplate() {
return template;
}
#JsonProperty
public void setTemplate(String template) {
this.template = template;
}
#JsonProperty
public String getDefaultName() {
return defaultName;
}
#JsonProperty
public void setDefaultName(String name) {
this.defaultName = name;
}
}
and my entity:
#Entity
#Table(name = "book")
#NamedQueries({
#NamedQuery(
name = "library.core.Book.findAll",
query = "SELECT b FROM book b"
)
})
public class Book{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "title")
#NotNull
private String title;
#Column(name = "author")
#NotNull
private String author;
#Column(name = "date")
private long date;
#Column(name = "description")
private String description;
#Column(name = "image")
private String image;
public Book(String title, String author){
this.title = title;
this.author = author;
}
#JsonProperty
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#JsonProperty
public Long getId() {
return id;
}
#JsonProperty
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
#JsonProperty
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
#JsonProperty
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#JsonProperty
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public void setId(Long id) {
this.id = id;
}
}
I have already been to many tutorials but none of them really explains how to configure hibernate. Thank you in advance.

I have finally solved this problem, which was not a big deal actually. Just a small mistake as it was expected.
My problem was a Book class, IDE automatically imported the java library called Book in the LibraryApplication class, so DB was not mapping it.
On the other hand, in the Book class the named query should be as follows:
#NamedQuery(
name = "library.core.Book.findAll",
query = "SELECT b FROM Book b"
)
My mistake: I was writing Book with small letter.

Related

No adding entity in a manytoone relationship using spring boot and jpa

I'm new in spring boot, I'm looking for help with this problem: I have two entities connected by a ManytoOne relationship. The entities are course and professor.
The professor Entity:
#Entity
#Table(name = "professor")
public class Professor implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idProfessor;
private String name;
private String lastName;
private String phone;
private String mail;
#Fetch(FetchMode.JOIN)
#OneToMany(mappedBy = "professor", cascade= CascadeType.ALL)
private List<Course> courses;
public Professor() {
}
public Long getIdProfessor() {
return idProfessor;
}
public void setIdProfessor(Long idProfessor) {
this.idProfessor = idProfessor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
}
The Course Entity:
#Entity
#Table(name = "course")
public class Course implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idCourse;
private String title;
private String description;
#ManyToOne
#JoinColumn(name="professor_id")
private Professor professor;
#ManyToMany(mappedBy = "courses")
private List<Student> students;
public Course() {}
public Long getIdCourse() {
return idCourse;
}
public void setIdCourse(Long idCourse) {
this.idCourse = idCourse;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
I also created a rest controller to create Course and I defined POST endpoint like this:
#PostMapping(value="/create")
public Course createCourse(#RequestBody Course course) {
return courseRepo.save(course);
}
When I add a new course in postman, the course is added but it is not assigned to the corresponding professor (an existing professor in the database), "idProfessor" is always assigned to NULL. Here is an example of POST API execution in postman and the result in MySQL.
postman
mysql
Any suggestions?

How to solve HHH000346 Error using hibernate 5 and mysql?

I'm studying restful service and views.
Regarding it, I use mysql and hibernate 5.
My data tables are two and have reference relation.
The problem occurs when I update the primary key.
When I add new one then update existing data in another table (they have reference relation), HHH000346: Error during managed flush occurs.
I already search on google, but I couldn't find the answer.
This is my Entity classes.
#Entity
#Table(name = "users")
#EntityListeners(AuditingEntityListener.class)
public class User {
private long serial;
private String username;
private String password;
public User() {
}
public User(long serial, String username, String password) {
setSerial(serial);
setUsername(username);
setPassword(password);
}
#Column(name = "serial", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
public long getSerial() {
return serial;
}
public void setSerial(long serial) {
this.serial = serial;
}
#Id
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password", nullable = false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "serial: " + this.serial + ", username: " + this.username + ", password: " + this.password;
}
}
Entity
#Table(name = "sites")
#EntityListeners(AuditingEntityListener.class)
#IdClass(Site.class)
public class Site implements Serializable{
#ManyToOne
#JoinColumn(name="username",foreignKey=#ForeignKey(name="username"))
private String username;
private String siteURL;
#Id
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Id
public String getSiteURL() {
return siteURL;
}
public void setSiteURL(String siteName) {
this.siteURL = siteName;
}
}
And this is class had problem.
public class UserController {
#Autowired
private UserRepository userRepository;
#Autowired
private SiteRepository siteRepository;
private CryptoUtil passwordEncoder = new CryptoUtil();
...
#PutMapping("/users/{username}")
public User updateUser(#PathVariable(value = "username") String username, #Valid #RequestBody User userDetails)
throws ResourceNotFoundException {
User user = userRepository.findById(username)
.orElseThrow(() -> new ResourceNotFoundException("User not found on :: " + username));
List<Site> sites = siteRepository.findByUsername(user.getUsername());
userDetails.setPassword(passwordEncoder.encryptSHA256(userDetails.getPassword()));
final User updateUser = userRepository.save(userDetails);
for (Site site : sites)
{
site.setUsername(userDetails.getUsername());
site = siteRepository.save(site);
}
userRepository.delete(user);
return updateUser;
}
....
}
The for-each statement occurs error.
PLEASE HELP ME
Why did you do this?
#ManyToOne
#JoinColumn(name="username",foreignKey=#ForeignKey(name="username"))
private String username;
It should be:
#ManyToOne
#JoinColumn(name="username",foreignKey=#ForeignKey(name="username"))
private User user;
I'll also suggest you to use the primary key as foreign key.
And you can't have multiple #Id in an entity.

Spring Boot: How to retrieve the username by user_id?

I have already connected my springboot to MySQL database. I want to display the username when user_id is specified in the HTTP request. e.g. http://8080/user/1 must display the name of the user with user_id 1.
The table contains attributes as:
| Integer user_id; | String username; | String fathername; | String mothername;
I have already tried this code in by Controller class but i does not seem to be working
#RequestMapping("/{userid}")
#ResponseBody
public String getById(Integer userid) {
String name="";
try {
Optional<Persondetails> persondetails=persondetailsRepository.findById(personid);
name = String.valueOf(userdetails.getName());
}
catch (Exception ex) {
return "Name not found";
}
return "The Name of the user is : " + name;
}
my repository code:
import java.util.List;
import java.util.Optional;
public interface UserdetailsRepository extends JpaRepository<Userdetails, Integer> {
public Optional<Userdetails> findById(Integer userid);
}
It says getName() is undefined for the type Optional
But i have defined it in Userdetails class
public class Userdetails {
#Id
#GeneratedValue
#Column(name="user_id")
private Integer userid;
#Column(name="name")
private String name;
#Column (name="fathers_name")
private String fathersname;
#Column(name="mothers_name")
private String mothersname;
public Userdetails() {
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getFathersname() {
return fathersname;
}
public void setFathersname(String fathersname) {
this.fathersname = fathersname;
}
public void setMothersname(String mothersname) {
this.mothersname = mothersname;
}
public String getMothersname() {
return mothersname;
}
}
It's missing the method type GET, you can do by two options:
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
OR
#GetMapping("/{id}")
public String getString(#PathVariable("id") int id) {
return "Helloworld";
}
Spring boot Connect with Mysql and get Data.
application.properties
server.contextPath=/demo-user
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
*Controller.Java
#RequestMapping({"/users"})
public class UserController {
#Autowired
private UserService userService;
#GetMapping(path = {"/{id}"})
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
}
UserService.java
public interface UserService {
User findById(int id);
}
UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository repository;
#Override
public User findById(int id) {
return repository.findOne(id);
}
}
UserRepository .java
public interface UserRepository extends Repository<User, Integer> {
User findOne(int id);
}
User.java
#Entity
#Table(name = "user")
public class User {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String firstName;
#Column
private String lastName;
#Column
private String email;
//setter and getter
}
Make request from browser or application.
http://localhost:8080/demo-user/users/1

Why JPA Hibernate changes the name of the field?

In model class I have isActive field with is boolean, that represent the is_active field in MySql DB. Here is whole model class:
package ca.gatin.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "Account")
public class Account {
#Id
#GeneratedValue
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(nullable = false, unique = true)
private String email;
#Column(nullable = false)
private String password;
#Column(name = "is_active", nullable = false)
private boolean isActive;
#Column(name = "date_created")
private Date dateCreated;
#Column(name = "date_last_modified")
private Date dateLastModified;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Date getDateLastModified() {
return dateLastModified;
}
public void setDateLastModified(Date dateLastModified) {
this.dateLastModified = dateLastModified;
}
}
But when I fetch account let's say through REST API like:
#RequestMapping(
value = "/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ServiceResponse<Account> getAll(#PathVariable("id") Long id) {
ServiceResponse<Account> serviceResponse = accountService.getAccountById(id);
return serviceResponse;
}
In a reply object I get isActive field renamed by Hibernate to "active" like this:
{
"id": 19,
"firstName": "Julia",
"lastName": "Sarandi",
"email": "julia#gatin.ca",
"password": "111111",
"dateCreated": 1451293826000,
"dateLastModified": null,
"active": true
}
Why? Why all other field's names stay same as in Account class, but isActive is renamed?
That is one question, and another question is:
I am new in Hibernate, and I do no understand why in logs of Hibernate DB requests is shows some weird queries:
Hibernate: select account0_.id as id1_0_0_, account0_.date_created as date_cre2_0_0_, account0_.date_last_modified as date_las3_0_0_, account0_.email as email4_0_0_, account0_.first_name as first_na5_0_0_, account0_.is_active as is_activ6_0_0_, account0_.last_name as last_nam7_0_0_, account0_.password as password8_0_0_ from Account account0_ where account0_.id=?
What query language is it? What are symbols: "0_", "0_0_". Can I switch logs to show MySQL queries to make it more understandable?
FYI
In my application.properties file I have following configuration:
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
Change getter and setter method name for isActive field as:
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
Then it return isActive in response.
That has nothing to do with Hibernate, and everything to do with your JSON marshaller. Spring uses Jackson, and Jackson uses bean properties (i.e. getters) to access the data and transform them to JSON fields. Your getter is named isActive(), and thus corresponds to a bean property named active, hence the name of the attribute in the JSON.
If you want the JSON field to be named isActive, then your getter should be isIsActive(). Or much better, you should annotate it with #JsonProperty("isActive").
To answer your second question, the query is a SQL query, generated by Hibernate. It changes the name of tables and assigns aliases to columns mainly to disambiguate tables, and fields of different tables that could have the same name, AFAIK.

JSON to POJO using Apache Camel and hibernate

Apache camel is using a route wich is listening to a specific url. the json from this url is then transformed to pojo classes and inserted in a mySQL database. Everything is working fine, except my foreign key still remains null. I'm using spring framework btw.
Here is the url where you can find the data:
https://builds.apache.org:443/job/Accumulo-1.5/api/json
Here is my routedefinition for camel
#Component
public class JenkinsConfigurationRouteBuilder extends SpringRouteBuilder {
private Logger logger = LoggerFactory.getLogger(JenkinsConfigurationRouteBuilder.class);
#Override
public void configure() throws Exception {
logger.info("Configuring route");
//Properties die hij niet vindt in de klasse negeren
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
DataFormat jenkinsConfigFormat = new JacksonDataFormat(objectMapper, JenkinsConfiguration.class);
from("timer://foo?fixedRate=true&delay=0&period=200000&repeatCount=1")
.routeId("jsonToJenkinsConfiguration")
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.to("https://builds.apache.org:443/job/Accumulo-1.5/api/json")
.convertBodyTo(String.class)
.unmarshal(jenkinsConfigFormat) //instance van JenkinsConfiguration
.log(LoggingLevel.DEBUG, "be.kdg.teamf", "Project: ${body}")
.to("hibernate:be.kdg.teamf.model.JenkinsConfiguration");
}
}
My POJO class
#Entity(name = "jenkinsConfiguration")
public class JenkinsConfiguration extends Configuration implements Serializable {
#Column
#JsonProperty("displayName")
private String name;
#JsonProperty("healthReport")
#JsonIgnore
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = ("jenkinsConfig"))
private Collection<HealthReport> healthReport;
#JsonProperty("builds")
#JsonIgnore
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = ("jenkinsConfig"))
private Collection<Build> builds;
#JsonProperty("modules")
#JsonIgnore
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = ("jenkinsConfig"))
private Collection<Module> modules;
public JenkinsConfiguration() {
}
public JenkinsConfiguration(Collection<Build> builds, Collection<HealthReport> healthReport, Collection<Module> modules, String name) {
this.builds = builds;
this.healthReport = healthReport;
this.modules = modules;
this.name = name;
}
public Collection<Build> getBuilds() {
return builds;
}
public Collection<HealthReport> getHealthReport() {
return healthReport;
}
public Collection<Module> getModules() {
return modules;
}
public String getName() {
return name;
}
public void setBuilds(Collection<Build> builds) {
this.builds = builds;
}
public void setHealthReport(Collection<HealthReport> healthReport) {
this.healthReport = healthReport;
}
public void setModules(Collection<Module> modules) {
this.modules = modules;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
Let us take the builds for instance.
As you can see, this pojo class contains a list from builds. A JenkinsConfiguration can contain more builds. One build belongs to one JenkinsConfiguration.
This is my Build class:
#XmlRootElement(name = "builds")
#Entity(name = "build")
public class Build implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int Id;
#Column
#JsonProperty("number")
private Integer number;
#Column
#JsonProperty("url")
private String url;
#JsonBackReference
#OnDelete(action = OnDeleteAction.CASCADE)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "jenkinsConfig")
private JenkinsConfiguration jenkinsConfig;
public Build() {
}
public Build(JenkinsConfiguration jenkinsConfig, Integer number, String url) {
this.jenkinsConfig = jenkinsConfig;
this.number = number;
this.url = url;
}
public int getId() {
return Id;
}
public JenkinsConfiguration getJenkinsConfig() {
return jenkinsConfig;
}
public Integer getNumber() {
return number;
}
public String getUrl() {
return url;
}
public void setId(int id) {
Id = id;
}
public void setJenkinsConfig(JenkinsConfiguration jenkinsConfig) {
this.jenkinsConfig = jenkinsConfig;
}
public void setNumber(Integer number) {
this.number = number;
}
public void setUrl(String url) {
this.url = url;
}
}
My question: how come that my foreign key is not set for the build class? it remains null.
Doe I need to update it manually or something? If so, how do I do that in spring?
Any help would me much appreciated!
Fixed it by updating the records in my database like so:
Camel:
from("hibernate:be.kdg.teamf.model.Build?delay=1s")
.routeId("buildFkBuild")
.startupOrder(3)
.shutdownRunningTask(ShutdownRunningTask.CompleteAllTasks)
.to("bean:buildFK?method=processBuild")
.log(LoggingLevel.DEBUG, "be.kdg.teamf", "Project: ${body}")
.to("hibernate:be.kdg.teamf.model.Build");
Bean:
#Consumed
public Build processBuild(Build build) {
//updaten van foreign key
build.setJenkinsConfig(jenkinsConfiguration);
return build;
}