if a java object has a auto-increment ID field, should the Database table field should be auto-increment as well?
for example
public class Company {
private static int countID = 0;
private int companyID;
private String name;
private String email;
private String password;
private List<Coupon> couponsList;
public Company(int companyID, String name, String email, String password, List<Coupon> couponsList) {
this.companyID = companyID+=1;
this.name = name;
this.email = email;
this.password = password;
this.couponsList = couponsList;
}
you can see that the companyID field is generated automatically.
i have created this table in my SQL server
CREATE TABLE `companies` (
`ID` int NOT NULL AUTO_INCREMENT,
`NAME` varchar(200) DEFAULT NULL,
`EMAIL` varchar(200) DEFAULT NULL,
`PASSWORD` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`)
how should I connect the Java field (commpanID) to the sql field (ID)?
No. They are different things. Auto-incremented columns in MySQL are not guaranteed to be gapless. Gaps can occur for multiple reasons. The most common are:
Concurrent transactions.
Deletion.
It sounds like you have a unique identifier in Java which is either redundant or an item of data. If the latter, then add it as an additional column.
More likely, though, you might want to reconsider your design, so there is only one auto-incremented value for a given record. I would recommend using the one in the database, because that would apply regardless of how inserts are made into the database.
It isn't compulsory to create and unique id field in the database . You can instead change the table like-->
CREATE TABLE companies (
'COMPANYID' int NOT NULL,
`NAME` varchar(200) DEFAULT NULL,
`EMAIL` varchar(200) DEFAULT NULL,
`PASSWORD` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`)
since you are auto incrementing the same the same value twice , it will create some problems.
your ID column will be like this-->
Id|
---
2 |
---
4 |
--
6 |
--
8 |
it will increment the values twice
Related
I'm using this hibernate-types that allows hibernate to translate SQL layer data types into java classes in my springboot application, here I'm trying to add a text array field called user array.
#Entity
#Table(name = "user_update")
#Getter
#Setter
#NoArgsConstructor
#RequiredArgsConstructor
#TypeDef(name = "list-array", typeClass = ListArrayType.class)
public class UserUpdate {
#Id #NonNull private String userKey;
#Column #NonNull private String userName;
#Column #NonNull private Instant updatedAt;
#Type(type = "list-array")
#Column(columnDefinition = "text[]")
#NonNull
private List<String> userArray;
}
I can insert data into the table, but now I want to add a test and I see the following error message from the table.sql
CREATE TABLE IF NOT EXISTS user_update (
user_key VARCHAR(255) NOT NULL,
user_name VARCHAR(255) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
user_array TEXT ARRAY NOT NULL,
PRIMARY KEY(org_key)
);
maybe it is because the test I'm running uses #DataJpaTest and for some reason it can not recognize the new text[] field ?
Error executing DDL "create table user_update (user_key varchar(255) not null, user_name varchar(255), user_array text[], updated_at timestamp, primary key (user_key))" via JDBC Statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "create table user_update (user_key varchar(255) not null, user_name varchar(255), user_array text[*][], updated_at timestamp, primary key (user_key))"; expected "(, ARRAY, INVISIBLE, VISIBLE, NOT, NULL, AS, DEFAULT, GENERATED, ON, NOT, NULL, DEFAULT, NULL_TO_DEFAULT, SEQUENCE, SELECTIVITY, COMMENT, CONSTRAINT, COMMENT, PRIMARY, UNIQUE, NOT, NULL, CHECK, REFERENCES, ,, )"; SQL statement:
With #DataJpaTest Spring will instruct Hibernate to create the schema and that will use the information that you provided in your annotations, but it seems this is not legal for H2.
Try using the following instead:
#Column(columnDefinition = "text array")
I have a products table that contains especially a product_name and a product_type.
For certain product types, I'd like to create some kind of overlay mapping table that replaces the value in product_name.
In pure mysql, I would solve this as follows:
CREATE TABLE products (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
product_price;
product_quantity;
...
)
#Entity
public class Product {
long id;
String product_type;
String product_name;
String product_price;
...
}
CREATE TABLE product_mapping (
id int NOT NULL AUTO_INCREMENT,
product_type varchar(20) NOT NULL,
product_name varchar(255) NOT NULL,
PRIMARY KEY (id)
);
My goal: if product_mapping contains the product_type, override the product_name. Else, stick to the value in products.product_name table.
SELECT ..., ifnull(product_mapping.product_name, products.product_name) AS product_name
FROM products
LEFT JOIN product_mapping ON products.product_type = product_mapping.product_type;
But how could I create the same mapping with a hibernate #Entity
Sidenote: A #Formula creates an additional SELECT for each query, whose result is merged into the #Entity. I'm looking for a JOIN!
Using
Hibernate 5.3, Spring Boot 2.1, MySQL, that runs in Windows 10 OS.
What I know
I have verified on my phpmyadmin the case of the attributes. And as long the case were the same as the attributes of my Entity class you don't have to explicitly define the column name in that Entity. And using #Column(name="tableattribute") is not required.
Problem
Once I executes the query, the number of row has been retrieved correctly. For example, my database contains 5 record, the List contains 5 employee objects, but all its attributes of the Entity always returns as null value.
I want to remove explicitly declaring the column name on each attribute and ensure that it will work in the actual server which might cause problem with the case of column name and the attribute name.
Tried
I tried to add #Column('column Name all lowercase') on each attributes and It retrieve the value.
Upon learning this, I verified the table column if it is lower case, but is not in lower case. Instead, It still follow the camel-case that is in my SQL command to create the table.
MySQL Table
CREATE TABLE `personal` (
`empID` int(11) NOT NULL,
`empNumber` varchar(15) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '',
`surname` varchar(50) NOT NULL DEFAULT '',
`firstname` varchar(50) NOT NULL DEFAULT '',
`middlename` varchar(50) NOT NULL DEFAULT '',
`middleInitial` varchar(10) DEFAULT NULL,
`nameExtension` varchar(10) DEFAULT '',
`salutation` varchar(15) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Entity
This Entity is now working fine as long as #Column and specify the column name in lowercase. But it is annoying to add each attribute with #Column and specify the name of the field in all lower case.
#Entity
#Table(name="personal")
public class Employee implements Serializable {
#Id
#Column(name="empID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotNull
#Column(name="empnumber")
private String empNumber;
private String surname;
private String firstname;
private String middlename;
#Column(name="middleinitial")
private String middleInitial;
#Column(name="nameextension")
private String nameExtension;
}
Actual Query Snippet on DAO
#Autowired
private EntityManager entityManager;
#Override
public List<Employee> findAll() {
Session currentSession = entityManager.unwrap(Session.class);
Query<Employee> query = currentSession.createQuery("from Employee", Employee.class);
return query.getResultList();
}
You can change that behavior by setting
spring.jpa.hibernate.naming.physical-strategy
spring.jpa.hibernate.naming.implicit-strategy
properties in your application.properties. On how to implement the strategies yourself, you can check out official docs.
Edit 1:
spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy = org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
We are five students in a team working on a project using SCRUM methode.
Our first sprint was WEB application...
Now, we are working at the second sprint which is Desktop application with JAVA.
In the first sprint(Sprint Web),we have created our database using FOS_USER Bundle, this database contains 'User' table, his sql script is(some columns):
DROP TABLE IF EXISTS `User`;
CREATE TABLE IF NOT EXISTS `User` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(180) COLLATE utf8_unicode_ci NOT NULL,
`username_canonical` varchar(180) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(180) COLLATE utf8_unicode_ci NOT NULL,
`email_canonical` varchar(180) COLLATE utf8_unicode_ci NOT NULL,
`enabled` tinyint(1) NOT NULL,
`salt` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`last_login` datetime DEFAULT NULL,
`confirmation_token` varchar(180) COLLATE utf8_unicode_ci DEFAULT NULL,
`password_requested_at` datetime DEFAULT NULL,
`roles` longtext COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:array)',
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_1D1C63B392FC23A8` (`username_canonical`),
UNIQUE KEY `UNIQ_1D1C63B3A0D96FBF` (`email_canonical`),
UNIQUE KEY `UNIQ_1D1C63B3FF631228` (`etablissement_id`),
UNIQUE KEY `UNIQ_1D1C63B3C05FB297` (`confirmation_token`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Now, in the sprint java, we have generated the entities from database using Netbeans tool, and we get this class(some attributs):
public class User{
private Integer id;
private String username;
private String usernameCanonical;
private String email;
private String emailCanonical;
private short enabled;
private String salt;
private String password;
private Date lastLogin;
private String confirmationToken;
private Date passwordRequestedAt;
private String roles;
}
Now, we need to persist(/get to authentificate) an User object into(/from) this database, but the problem is, the password was crypted with FOS_USER Bundle.So what is the way to decrepte/encrypte this password.
Our DAOUser is like this!?
public void ajouter(User user) {
String req = "INSERT INTO User (nom,username,email,enabled,salt,password,roles) VALUES (?,?,?,?,?,?)" ;
PreparedStatement pre;
try {
pre = connection.prepareStatement(req);
pre.setString(1, user.getUsername());
pre.setString(2, user.getEmail());
pre.setShort(3, user.getEnabled());
//Some thing wrong : exp in database {username:Zain,salt:'0Yi3LZANkpfMsnhbn2XHA00cASLCGVfWc7TJWNOjXsk')
pre.setString(4, user.getSalt());
//Some thing wrong : exp in database {username:Zain,passowrd:'qXSSYBDXWQA/ZcbPVOoBKzd5oshTkQP0Q3AeEilnh47Mcrc9uUZYDYwmRJiMKc7nRPvRx6k0eEJrc6HrrDvZtQ==')
pre.setString(5, user.getPassword());
//This Role must be unserialised(the equivalent unserialize method in php)
pre.setString(6,user.getRoles());
pre.executeUpdate();
} catch (SQLException ex) {
Logger.getLogger(EtablissementService.class.getName()).log(Level.SEVERE, null, ex);
}
}
You don't wan to decrypt password. It should be one way hash. To check validity of password, encrypt user input in the same way and check calculated hash to match the hash in the database
Im getting this error from hibernate when trying to do a criteria search
ERROR org.hibernate.property.access.spi.GetterMethodImpl - HHH000122:
IllegalArgumentException in class: packagename.domain.User, getter method of
property: id
For this criteria search
#Override
public List<Story> findStoryByAuthor(Long userId) throws Exception {
Criteria criteria = currentSession().createCriteria(Story.class);
criteria.add(Restrictions.eq("author", userId));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List<?> stories = criteria.list();
return (List<Story>) stories;
}
We are finding stories via the user that created it so here are the property definitions. Trying not to clutter this so if you guys want to see more code let me know.
Story has a Many to One relationship with User
#ManyToOne(fetch = FetchType.LAZY, targetEntity = User.class)
#JoinColumn(name = "author_user_id", referencedColumnName = "id")
public User getAuthor() {
return author;
}
Users have no reference to story but its id property is correctly annotated
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
And lastly the database structure
Stories Table
id bigint NOT NULL DEFAULT nextval('stories_seq'::regclass),
parent_id bigint,
author_user_id bigint NOT NULL,
title character varying(100) NOT NULL,
dt_created timestamp without time zone NOT NULL,
dt_last_updated timestamp without time zone NOT NULL DEFAULT now_utc(),
thumbs_up bigint DEFAULT 0,
thumbs_down bigint DEFAULT 0,
CONSTRAINT pk_stories PRIMARY KEY (id),
CONSTRAINT fk_stories_author_user_id_users FOREIGN KEY (author_user_id)
REFERENCES public.users (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
Users Table
id bigint NOT NULL DEFAULT nextval('users_seq'::regclass),
first_name character varying(255),
last_name character varying(255),
email character varying(255) NOT NULL,
user_name character varying(255),
password character varying(255),
phone character varying(255),
address character varying(500),
city character varying(255),
state character varying(255),
zip integer,
preferred_language character varying(255),
note character varying(32000),
active boolean DEFAULT true,
active_paid boolean DEFAULT false,
CONSTRAINT pk_user_id PRIMARY KEY (id),
CONSTRAINT users_unique_fields UNIQUE (email, user_name)
FYI
all basic dao functions (add, update and delete) work (full unit test coverage). I have another criteria search, almost identical but searches on the email field and works fine. so this error is something with the user reference
Please try with
criteria.add(Restrictions.eq("author.id", userId));
author property is of class User so you need to reference its id property for the equality.